Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
# Changelog
All notable changes to this project will be documented in this file.

## Release 2.2.0

### New features
- Basic authentication setup
- New function 'sendRequest'
- Check if persistent data to load provides all relevant parameters. Otherwise add default values

### Improvements
- 'sendInternalRequest' returns now the HTTP response
- FlowConfig handling
- Minor docu improvements

### Bugfix
- Wrong instance handling within FlowConfig
- FlowConfig priority was not instance specific
- Legacy bindings of ValueDisplay elements and FileUpload feature within UI did not work if deployed with VS Code AppSpace SDK
- UI differs if deployed via Appstudio or VS Code AppSpace SDK
- Fullscreen icon of iFrame was visible

## Release 2.1.0

### New features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,5 @@

.myCustomButton_CSK_Module_MultiHTTPClient {
border-radius: 30px;
padding-right: 0px;
padding: 11px;
}

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions CSK_Module_MultiHTTPClient/pages/src/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ export function convertToList(value) {
export function changeStyle(theme) {
const style: HTMLStyleElement = document.createElement('style');
style.id ='blub'

const toggleSW = document.querySelectorAll("davinci-toggle-switch")
toggleSW.forEach((userItem) => {
const shadowToggle = userItem.shadowRoot
const finalToggleSW = shadowToggle?.querySelector('div')
finalToggleSW?.classList.add('hasIcon')
});

if (theme == 'CSK_Style'){
var headerToolbar = `.sopasjs-ui-header-toolbar-wrapper { background-color: #FFFFFF; }`
var uiHeader = `.sopasjs-ui-header>.app-logo { margin-right:0px; }`
Expand Down
4 changes: 4 additions & 0 deletions CSK_Module_MultiHTTPClient/pages/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ document.addEventListener('sopasjs-ready', () => {
page_Setup.remove();

setTimeout(() => {
const element = document.querySelector("div.sjs-wrapper > div > div.sjs-fullscreen-toggle")
if(element) {
element.parentElement.removeChild(element)
}
document.title = 'CSK_Module_MultiHTTPClient'
}, 500);
})
35 changes: 34 additions & 1 deletion CSK_Module_MultiHTTPClient/project.mf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,14 @@ INFO: Other modules can check via "Script.isServedAsEvent" if event of sepecific
<desc>Notify if module can be used on device.</desc>
<param desc="Status" multiplicity="1" name="status" type="bool"/>
</event>
<event name="OnNewStatusBasicAuthentication">
<desc>Notify status if HTTP basic authentication should be used.</desc>
<param desc="Status" multiplicity="1" name="status" type="bool"/>
</event>
<event name="OnNewStatusBasicAuthenticationUser">
<desc>Notify user for basic authentication.</desc>
<param desc="Username" multiplicity="1" name="user" type="string"/>
</event>
<function name="setParameterName">
<desc>Function to set the name of the parameters if saved/loaded via the CSK_PersistentData module.</desc>
<param desc="Name of the parameter" multiplicity="1" name="name" type="string"/>
Expand Down Expand Up @@ -500,6 +508,31 @@ IMPORTANT: As instances start their own threads, the module needs to be restarte
<function name="resetModule">
<desc>Function to reset main configuration of module.</desc>
</function>
<function name="setBasicAuthentication">
<desc>Function to set status to use HTTP basic authentication.</desc>
<param desc="Status" multiplicity="1" name="status" type="bool"/>
</function>
<function name="setBasicAuthenticationUser">
<desc>Function to set user for HTTP basic authentication.</desc>
<param desc="User" multiplicity="1" name="user" type="string"/>
</function>
<function name="setBasicAuthenticationPassword">
<desc>Function to set password for user of HTTP basic authentication.</desc>
<param desc="Password" multiplicity="1" name="password" type="string"/>
</function>
<function name="sendRequestNUM">
<desc>Example of dynamically served function to send a request of a specific instance. +
NUM will be replaced by the number of instance (e.g. "sendRequest1"). +
INFO: Other modules can check via "Script.isServedAsFunction" if function of sepecific instance exists. +
Needs then to be called via "Script.callFunction".</desc>
<param desc="Mode of request." multiplicity="1" name="mode" ref="CSK_MultiHTTPClient.RequestMode" type="enum"/>
<param desc="Endpoint" multiplicity="1" name="endpoint" type="string"/>
<param desc="Port" multiplicity="1" name="port" type="int"/>
<param desc="Optional list of headers (JSON)." multiplicity="?" name="header" type="string"/>
<param desc="Body content (JSON)." multiplicity="?" name="body" type="string"/>
<param desc="Type of content." multiplicity="?" name="contentType" type="string"/>
<return desc="Response (JSON)" multiplicity="1" name="response" type="string"/>
</function>
</serves>
</crown>
<crown name="MultiHTTPClient_FC">
Expand Down Expand Up @@ -530,7 +563,7 @@ IMPORTANT: As instances start their own threads, the module needs to be restarte
</crown>
</crown>
<meta key="author">SICK AG</meta>
<meta key="version">2.1.0</meta>
<meta key="version">2.2.0</meta>
<meta key="priority">low</meta>
<meta key="copy-protected">false</meta>
<meta key="read-protected">false</meta>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ local multiHTTPClient_Instances = {} -- Handle all instances
local multiHTTPClientController = require('Communication/MultiHTTPClient/MultiHTTPClient_Controller')

if _G.availableAPIs.default and _G.availableAPIs.specific then
local setInstanceHandle = require('Communication/MultiHTTPClient/FlowConfig/MultiHTTPClient_FlowConfig')
require('Communication/MultiHTTPClient/FlowConfig/MultiHTTPClient_FlowConfig')
table.insert(multiHTTPClient_Instances, multiHTTPClient_Model.create(1)) -- Create at least 1 instance
multiHTTPClientController.setMultiHTTPClient_Instances_Handle(multiHTTPClient_Instances) -- share handle of instances
setInstanceHandle(multiHTTPClient_Instances)
else
_G.logger:warning("CSK_MultiHTTPClient: Relevant CROWN(s) not available on device. Module is not supported...")
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ processingParams.clientActivated = scriptParams:get('clientActivated')
processingParams.hostnameVerification = scriptParams:get('hostnameVerification')
processingParams.peerVerification = scriptParams:get('peerVerification')
processingParams.cookieStore = scriptParams:get('cookieStore')
processingParams.basicAuthentication = scriptParams:get('basicAuthentication')
processingParams.basicAuthenticationUser = scriptParams:get('basicAuthenticationUser')
processingParams.basicAuthenticationPassword = scriptParams:get('basicAuthenticationPassword')

processingParams.clientAuthentication = scriptParams:get('clientAuthentication')
processingParams.caBundleFileName = scriptParams:get('caBundleFileName')
processingParams.clientCertificateType = scriptParams:get('clientCertificateType')
Expand Down Expand Up @@ -119,6 +123,11 @@ local function updateClient()
clientObject = HTTPClient.create()

clientObject:setVerbose(processingParams.verboseMode)

if processingParams.basicAuthentication then
clientObject:setAuthCredentials(processingParams.basicAuthenticationUser, processingParams.basicAuthenticationPassword)
end

if processingParams.clientAuthentication then
if File.exists(processingParams.caBundleFileName) then
clientObject:setCABundle(processingParams.caBundleFileName)
Expand Down Expand Up @@ -179,12 +188,14 @@ end

--- Function to execute a request
---@param tempRequestActive bool Status if it is just a temporarly configured request or a preconfigured one
---@param showResponse bool Status if repsonse should be notified as event (e.g. to show it on UI)
---@param eventName string Name of event to notify the response
local function sendRequest(tempRequestActive, showResponse, eventName)
---@param showResponse bool Status if response should be notified as event (e.g. to show it on UI)
---@param eventName string? Optional name of event to notify the response
---@return string response Response of HTTP request
local function sendInternalRequest(tempRequestActive, showResponse, eventName)

local timerQueueSize = 0
local eventQueueSize = 0
local jsonResponse = {}

if tempRequestActive then
updateInternalRequest(processingParams)
Expand All @@ -200,37 +211,50 @@ local function sendRequest(tempRequestActive, showResponse, eventName)

if timerQueueSize >= processingParams.queueSize-1 or eventQueueSize >= processingParams.queueSize-1 then
_G.logger:warning(nameOfModule .. ": Internal request queue too high '(Timer:" .. tostring(timerQueueSize) .. '/Events:' .. tostring(eventQueueSize) .. ")'. Will skip new requests...")
return ''
else
local tic = DateTime.getTimestamp()

local response = clientObject:execute(request)
local procTime = DateTime.getTimestamp() - tic

local success = HTTPClient.Response.getSuccess(response)
jsonResponse.Success = tostring(success)
_G.logger:fine(nameOfModule .. ": Response success = " .. tostring(success))

-- Check response
local responseMessage = 'After ' .. tostring(procTime) .. 'ms --> ' .. 'Request success = ' .. tostring(success) .. '\n'
responseMessage = responseMessage .. 'Code: ' .. HTTPClient.Response.getStatusCode(response) .. '\n'
local statusCode = HTTPClient.Response.getStatusCode(response)
responseMessage = responseMessage .. 'Code: ' .. statusCode .. '\n'
jsonResponse.StatusCode = statusCode

if success then
-- Check if extended information of the response should be shown
if processingParams.extendedResponse then
responseMessage = responseMessage .. 'Request content type: ' .. HTTPClient.Response.getContentType(response) .. '\n'
local contentType = HTTPClient.Response.getContentType(response)
responseMessage = responseMessage .. 'Request content type: ' .. contentType .. '\n'
jsonResponse.ContentType = contentType

local tempKeys = HTTPClient.Response.getHeaderKeys(response)
jsonResponse.Headers = {}
for _, headerKeys in pairs(tempKeys) do
jsonResponse.Headers[headerKeys] = {}

local suc, tempValues = HTTPClient.Response.getHeaderValues(response, headerKeys)
for _, headerValue in pairs(tempValues) do
responseMessage = responseMessage .. 'Header-key: ' .. headerKeys .. ' = ' .. headerValue .. '\n'
table.insert(jsonResponse.Headers[headerKeys], headerValue)
end
end
end

jsonResponse.Response = HTTPClient.Response.getContent(response)
responseMessage = responseMessage .. helperFuncs.jsonLine2Table(HTTPClient.Response.getContent(response)) .. '\n'
else
local error = HTTPClient.Response.getError(response)
local errorDetail = HTTPClient.Response.getErrorDetail(response)
jsonResponse.Error = error
jsonResponse.ErrorDetail = errorDetail
responseMessage = responseMessage .. 'Error = ' .. error .. '\n' .. 'Error details = ' .. errorDetail .. '\n'
end
if eventName then
Expand All @@ -244,8 +268,27 @@ local function sendRequest(tempRequestActive, showResponse, eventName)
Script.notifyEvent("MultiHTTPClient_OnNewValueToForward" .. multiHTTPClientInstanceNumberString, "MultiHTTPClient_OnNewResponseMessage", responseMessage)
end
end
return json.encode(jsonResponse)
end
end

local function sendRequest(mode, endpoint, port, header, body, contentType)
processingParams.extendedResponse = true
processingParams.requestMode = mode
processingParams.requestEndpoint = endpoint
processingParams.requestPort = port

if body then
processingParams.requestContent = body
else
processingParams.requestContent = ''
end

local response = sendInternalRequest(true, false)

return response
end
Script.serveFunction('CSK_MultiHTTPClient.sendRequest' .. multiHTTPClientInstanceNumberString, sendRequest, 'string, string, int, string:?, string:?, string:?', 'string')

--- Function to set timer if request should be executed periodically
---@param requestName string Name of preconfigured request
Expand All @@ -260,9 +303,9 @@ local function setTimer(requestName)
if processingParams.clientActivated then
setSpecificRequest(requestName)
if selectedRequest == requestName then
sendRequest(false, true, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
sendInternalRequest(false, true, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
else
sendRequest(false, false, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
sendInternalRequest(false, false, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
end
end
end
Expand Down Expand Up @@ -306,9 +349,9 @@ local function setRegisteredEvent(requestName)
end
setSpecificRequest(requestName)
if selectedRequest == requestName then
sendRequest(false, true, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
sendInternalRequest(false, true, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
else
sendRequest(false, false, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
sendInternalRequest(false, false, "MultiHTTPClient_OnNewReponse" .. multiHTTPClientInstanceNumberString .. '_' .. processingParams.requests[requestName].requestName)
end
end
end
Expand Down Expand Up @@ -501,7 +544,7 @@ local function handleOnNewProcessingParameter(multiHTTPClientNo, parameter, valu

elseif parameter == 'sendRequest' then
if processingParams.clientActivated then
sendRequest(true, true)
sendInternalRequest(true, true)
end

elseif parameter == 'headerUpdate' then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,10 @@

require('Communication.MultiHTTPClient.FlowConfig.MultiHTTPClient_SendRequest')

-- Reference to the multiHTTPClient_Instances handle
local multiHTTPClient_Instances

--- Function to react if FlowConfig was updated
local function handleOnClearOldFlow()
if _G.availableAPIs.default and _G.availableAPIs.specific then
for i = 1, # multiHTTPClient_Instances do
if multiHTTPClient_Instances[i].parameters.flowConfigPriority then
CSK_MultiHTTPClient.clearFlowConfigRelevantConfiguration()
break
end
end
CSK_MultiHTTPClient.clearFlowConfigRelevantConfiguration()
end
end
Script.register('CSK_FlowConfig.OnClearOldFlow', handleOnClearOldFlow)

--- Function to get access to the multiHTTPClient_Instances
---@param handle handle Handle of multiHTTPClient_Instances object
local function setMultiHTTPClient_Instances_Handle(handle)
multiHTTPClient_Instances = handle
end

return setMultiHTTPClient_Instances_Handle
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ local function create(instance, requestName, mode, protocol, endpoint, port)
local fullInstanceName = tostring(instance) .. tostring(requestName)

-- Check if same instance is already configured
if instance < 1 or nil ~= instanceTable[fullInstanceName] then
if instanceTable[fullInstanceName] ~= nil then
_G.logger:warning(nameOfModule .. ': Instance invalid or already in use, please choose another one')
return nil
else
-- Otherwise create handle and store the restriced resource
local handle = Container.create()
instanceTable[instance] = instance
instanceTable[fullInstanceName] = fullInstanceName
Container.add(handle, 'Instance', instance)
Container.add(handle, 'RequestName', requestName)
Container.add(handle, 'Mode', mode)
Expand Down
Loading