Merge pull request #76 from saschal-j5int/master-fix-ioswebserver

Fix iOS webserver
This commit is contained in:
Michael Bykovski 2023-07-01 19:45:07 +02:00 committed by GitHub
commit 53beb743bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,13 +3,13 @@
let TIMEOUT: Int = 60 * 3 * 1000000 let TIMEOUT: Int = 60 * 3 * 1000000
var webServer: GCDWebServer = GCDWebServer() var webServer: GCDWebServer = GCDWebServer()
var responses = SynchronizedDictionary<AnyHashable,Any?>() var requests = SynchronizedDictionary<AnyHashable, (GCDWebServerRequest, GCDWebServerCompletionBlock)>()
var onRequestCommand: CDVInvokedUrlCommand? = nil var onRequestCommand: CDVInvokedUrlCommand? = nil
override func pluginInitialize() { override func pluginInitialize() {
self.webServer = GCDWebServer() self.webServer = GCDWebServer()
self.onRequestCommand = nil self.onRequestCommand = nil
self.responses = SynchronizedDictionary<AnyHashable,Any?>() self.requests = SynchronizedDictionary<AnyHashable,(GCDWebServerRequest, GCDWebServerCompletionBlock)>()
self.initHTTPRequestHandlers() self.initHTTPRequestHandlers()
} }
@ -18,7 +18,7 @@
var body = "" var body = ""
if dataRequest.hasBody() { if dataRequest.hasBody() {
body = String(data: dataRequest.data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) ?? "" body = dataRequest.data.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
} }
return [ return [
@ -26,8 +26,9 @@
"body": body, "body": body,
"headers": dataRequest.headers, "headers": dataRequest.headers,
"method": dataRequest.method, "method": dataRequest.method,
"path": dataRequest.url.path, "path": dataRequest.path,
"query": dataRequest.url.query ?? "" "query": dataRequest.url.query ?? "",
"bodyIsBase64": true // we only implement this for iOS so this way we can check if it is actually base64
] ]
} }
@ -44,50 +45,27 @@
return GCDWebServerFileResponse(file: path)! return GCDWebServerFileResponse(file: path)!
} }
func processRequest(request: GCDWebServerRequest, completionBlock: GCDWebServerCompletionBlock) { func processRequest(request: GCDWebServerRequest, completionBlock: @escaping GCDWebServerCompletionBlock) {
var timeout = 0 if (self.onRequestCommand == nil) {
print("No onRequest callback available. Ignore request")
return
}
// Fetch data as GCDWebserverDataRequest // Fetch data as GCDWebserverDataRequest
let requestUUID = UUID().uuidString let requestUUID = UUID().uuidString
// Transform it into an dictionary for the javascript plugin // Transform it into an dictionary for the javascript plugin
let requestDict = self.requestToRequestDict(requestUUID: requestUUID, request: request) let requestDict = self.requestToRequestDict(requestUUID: requestUUID, request: request)
// Save the request to when we receive a response from javascript
self.requests[requestUUID] = (request, completionBlock)
// Do a call to the onRequestCommand to inform the JS plugin // Do a call to the onRequestCommand to inform the JS plugin
if (self.onRequestCommand != nil) { let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: requestDict)
let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: requestDict) pluginResult?.setKeepCallbackAs(true)
pluginResult?.setKeepCallbackAs(true) self.commandDelegate.send(
self.commandDelegate.send( pluginResult,
pluginResult, callbackId: self.onRequestCommand?.callbackId
callbackId: self.onRequestCommand?.callbackId )
)
}
// Here we have to wait until the javascript block fetches the message and do a response
while self.responses[requestUUID] == nil {
timeout += 1000
usleep(1000)
}
// We got the dict so put information in the response
let responseDict = self.responses[requestUUID] as! Dictionary<AnyHashable, Any>
// Check if a file path is provided else use regular data response
let response = responseDict["path"] != nil
? fileRequest(request: request, path: responseDict["path"] as! String)
: GCDWebServerDataResponse(text: responseDict["body"] as! String)
if responseDict["status"] != nil {
response?.statusCode = responseDict["status"] as! Int
}
for (key, value) in (responseDict["headers"] as! Dictionary<String, String>) {
response?.setValue(value, forAdditionalHeader: key)
}
// Remove the handled response
self.responses.removeValue(forKey: requestUUID)
// Complete the async response
completionBlock(response!)
} }
@objc(onRequest:) @objc(onRequest:)
@ -113,7 +91,45 @@
@objc(sendResponse:) @objc(sendResponse:)
func sendResponse(_ command: CDVInvokedUrlCommand) { func sendResponse(_ command: CDVInvokedUrlCommand) {
self.responses[command.argument(at: 0) as! String] = command.argument(at: 1) do {
let requestUUID = command.argument(at: 0) as! String
if (self.requests[requestUUID] == nil) {
print("No matching request")
self.commandDelegate!.send(CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "No matching request"), callbackId: command.callbackId)
return
}
// We got the dict so put information in the response
let request = self.requests[requestUUID]?.0 as! GCDWebServerRequest
let completionBlock = self.requests[requestUUID]?.1 as! GCDWebServerCompletionBlock
let responseDict = command.argument(at: 1) as! Dictionary<AnyHashable, Any>
// Check if a file path is provided else use regular data response
let response = responseDict["path"] != nil
? fileRequest(request: request, path: responseDict["path"] as! String)
: GCDWebServerDataResponse(text: responseDict["body"] as! String)
if responseDict["status"] != nil {
response?.statusCode = responseDict["status"] as! Int
}
for (key, value) in (responseDict["headers"] as! Dictionary<String, String>) {
response?.setValue(value, forAdditionalHeader: key)
}
// Remove the handled request
self.requests.removeValue(forKey: requestUUID)
// Complete the async response
completionBlock(response!)
let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK)
self.commandDelegate!.send(pluginResult, callbackId: command.callbackId)
} catch let error {
print(error.localizedDescription)
self.commandDelegate!.send(CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription), callbackId: command.callbackId)
}
} }
@objc(start:) @objc(start:)