@cappitolian/http-local-server-swifter 0.0.13 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/cappitolian/plugins/httplocalserviceswifter/HttpLocalServerSwifter.java +66 -203
- package/android/src/main/java/com/cappitolian/plugins/httplocalserviceswifter/HttpLocalServerSwifterPlugin.java +6 -40
- package/dist/docs.json +44 -118
- package/dist/esm/definitions.d.ts +14 -142
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +4 -27
- package/dist/esm/index.js +6 -27
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +0 -6
- package/dist/esm/web.js +7 -33
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +12 -60
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +12 -60
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/HttpLocalServerSwifterPlugin/HttpLocalServerSwifter.swift +76 -246
- package/ios/Sources/HttpLocalServerSwifterPlugin/HttpLocalServerSwifterPlugin.swift +18 -44
- package/package.json +1 -1
|
@@ -2,338 +2,168 @@ import Foundation
|
|
|
2
2
|
import Swifter
|
|
3
3
|
import Capacitor
|
|
4
4
|
|
|
5
|
-
// MARK: - Protocol
|
|
6
5
|
public protocol HttpLocalServerSwifterDelegate: AnyObject {
|
|
7
6
|
func httpLocalServerSwifterDidReceiveRequest(_ data: [String: Any])
|
|
8
7
|
}
|
|
9
8
|
|
|
10
|
-
// MARK: - HttpLocalServerSwifter
|
|
11
9
|
@objc public class HttpLocalServerSwifter: NSObject {
|
|
12
|
-
// MARK: - Properties
|
|
13
10
|
private var webServer: HttpServer?
|
|
14
11
|
private weak var delegate: HttpLocalServerSwifterDelegate?
|
|
15
12
|
|
|
13
|
+
// Store callbacks that expect a JSON String containing the full response object
|
|
16
14
|
private static var pendingResponses = [String: (String) -> Void]()
|
|
17
15
|
private static let queue = DispatchQueue(label: "com.cappitolian.HttpLocalServerSwifter.pendingResponses", qos: .userInitiated)
|
|
18
16
|
|
|
19
|
-
private let defaultTimeout: TimeInterval =
|
|
17
|
+
private let defaultTimeout: TimeInterval = 10.0
|
|
20
18
|
private let defaultPort: UInt16 = 8080
|
|
21
19
|
|
|
22
|
-
// MARK: - Initialization
|
|
23
20
|
public init(delegate: HttpLocalServerSwifterDelegate) {
|
|
24
21
|
self.delegate = delegate
|
|
25
22
|
super.init()
|
|
26
23
|
}
|
|
27
24
|
|
|
28
|
-
deinit {
|
|
29
|
-
disconnect()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// MARK: - Public Methods
|
|
33
25
|
@objc public func connect(_ call: CAPPluginCall) {
|
|
34
|
-
// Stop existing server if running
|
|
35
26
|
self.disconnect()
|
|
36
|
-
|
|
37
27
|
self.webServer = HttpServer()
|
|
38
28
|
self.setupHandlers()
|
|
39
|
-
|
|
40
29
|
do {
|
|
41
|
-
try self.
|
|
30
|
+
try self.webServer?.start(defaultPort, forceIPv4: true)
|
|
42
31
|
let ip = Self.getWiFiAddress() ?? "127.0.0.1"
|
|
43
|
-
|
|
44
|
-
print("✅ HttpLocalServerSwifter: Server started on \(ip):\(self.defaultPort)")
|
|
45
|
-
|
|
46
|
-
call.resolve([
|
|
47
|
-
"ip": ip,
|
|
48
|
-
"port": self.defaultPort
|
|
49
|
-
])
|
|
32
|
+
call.resolve(["ip": ip, "port": self.defaultPort])
|
|
50
33
|
} catch {
|
|
51
|
-
print("❌ HttpLocalServerSwifter: Failed to start server - \(error.localizedDescription)")
|
|
52
34
|
call.reject("Failed to start server: \(error.localizedDescription)")
|
|
53
35
|
}
|
|
54
36
|
}
|
|
55
37
|
|
|
56
38
|
@objc public func disconnect(_ call: CAPPluginCall? = nil) {
|
|
57
|
-
|
|
39
|
+
webServer?.stop()
|
|
40
|
+
webServer = nil
|
|
41
|
+
Self.queue.async { Self.pendingResponses.removeAll() }
|
|
58
42
|
call?.resolve()
|
|
59
43
|
}
|
|
60
44
|
|
|
61
|
-
|
|
62
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Serializes the JS response dictionary to JSON to pass it back to the processing thread
|
|
47
|
+
*/
|
|
48
|
+
static func handleJsResponse(requestId: String, responseData: [String: Any]) {
|
|
63
49
|
queue.async {
|
|
64
50
|
if let callback = pendingResponses[requestId] {
|
|
65
|
-
|
|
51
|
+
if let jsonData = try? JSONSerialization.data(withJSONObject: responseData),
|
|
52
|
+
let jsonString = String(data: jsonData, encoding: .utf8) {
|
|
53
|
+
callback(jsonString)
|
|
54
|
+
}
|
|
66
55
|
pendingResponses.removeValue(forKey: requestId)
|
|
67
|
-
print("✅ HttpLocalServerSwifter: Response sent for requestId: \(requestId)")
|
|
68
|
-
} else {
|
|
69
|
-
print("⚠️ HttpLocalServerSwifter: No pending callback for requestId: \(requestId)")
|
|
70
56
|
}
|
|
71
57
|
}
|
|
72
58
|
}
|
|
73
59
|
|
|
74
|
-
// MARK: - Private Methods
|
|
75
|
-
private func disconnect() {
|
|
76
|
-
webServer?.stop()
|
|
77
|
-
webServer = nil
|
|
78
|
-
|
|
79
|
-
// Clear pending responses
|
|
80
|
-
Self.queue.async {
|
|
81
|
-
Self.pendingResponses.removeAll()
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
print("🛑 HttpLocalServerSwifter: Server stopped")
|
|
85
|
-
}
|
|
86
|
-
|
|
87
60
|
private func setupHandlers() {
|
|
88
61
|
guard let server = webServer else { return }
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return self?.
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
server["/:first/:second"] = { [weak self] request in
|
|
99
|
-
return self?.handleRequest(request) ?? self?.errorResponse() ?? .internalServerError
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
server["/:first/:second/:third"] = { [weak self] request in
|
|
103
|
-
return self?.handleRequest(request) ?? self?.errorResponse() ?? .internalServerError
|
|
62
|
+
|
|
63
|
+
// This closure handles EVERY request regardless of the path
|
|
64
|
+
let handler: ((HttpRequest) -> HttpResponse) = { [weak self] request in
|
|
65
|
+
if request.method == "OPTIONS" {
|
|
66
|
+
return self?.corsResponse() ?? .raw(204, "No Content", nil, nil)
|
|
67
|
+
}
|
|
68
|
+
return self?.processRequest(request) ?? .raw(500, "Internal Server Error", nil, nil)
|
|
104
69
|
}
|
|
105
70
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
private func handleRequest(_ request: HttpRequest) -> HttpResponse {
|
|
110
|
-
print("📨 HttpLocalServerSwifter: Received \(request.method) request to \(request.path)")
|
|
111
|
-
|
|
112
|
-
// Handle OPTIONS (CORS preflight)
|
|
113
|
-
if request.method == "OPTIONS" {
|
|
114
|
-
print("🔄 HttpLocalServerSwifter: Handling CORS preflight")
|
|
115
|
-
return corsResponse()
|
|
71
|
+
// Swifter needs a wildcard to catch everything including subpaths like /orders/123
|
|
72
|
+
server.middleware.append { request in
|
|
73
|
+
return handler(request)
|
|
116
74
|
}
|
|
117
|
-
|
|
118
|
-
return processRequest(request)
|
|
119
75
|
}
|
|
120
76
|
|
|
121
77
|
private func processRequest(_ request: HttpRequest) -> HttpResponse {
|
|
122
|
-
let method = request.method
|
|
123
|
-
let path = request.path
|
|
124
|
-
let body = extractBody(from: request)
|
|
125
|
-
let headers = extractHeaders(from: request)
|
|
126
|
-
let query = extractQuery(from: request)
|
|
127
|
-
|
|
128
78
|
let requestId = UUID().uuidString
|
|
129
79
|
var responseString: String?
|
|
130
|
-
|
|
131
|
-
// Setup semaphore for synchronous waiting
|
|
132
80
|
let semaphore = DispatchSemaphore(value: 0)
|
|
133
81
|
|
|
134
82
|
Self.queue.async {
|
|
135
|
-
Self.pendingResponses[requestId] = {
|
|
136
|
-
responseString =
|
|
83
|
+
Self.pendingResponses[requestId] = { jsResponse in
|
|
84
|
+
responseString = jsResponse
|
|
137
85
|
semaphore.signal()
|
|
138
86
|
}
|
|
139
87
|
}
|
|
140
88
|
|
|
141
|
-
//
|
|
142
|
-
|
|
89
|
+
// Map request to dictionary for TS
|
|
90
|
+
let requestData: [String: Any] = [
|
|
143
91
|
"requestId": requestId,
|
|
144
|
-
"method": method,
|
|
145
|
-
"path": path
|
|
92
|
+
"method": request.method,
|
|
93
|
+
"path": request.path,
|
|
94
|
+
"headers": request.headers,
|
|
95
|
+
"query": request.queryParams,
|
|
96
|
+
"body": String(bytes: request.body, encoding: .utf8) ?? ""
|
|
146
97
|
]
|
|
147
98
|
|
|
148
|
-
|
|
149
|
-
if let body = body, !body.isEmpty {
|
|
150
|
-
requestData["body"] = body
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if !headers.isEmpty {
|
|
154
|
-
requestData["headers"] = headers
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if !query.isEmpty {
|
|
158
|
-
requestData["query"] = query
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
print("📤 HttpLocalServerSwifter: Notifying delegate with requestId: \(requestId)")
|
|
99
|
+
DispatchQueue.main.async { self.delegate?.httpLocalServerSwifterDidReceiveRequest(requestData) }
|
|
162
100
|
|
|
163
|
-
// Notify on main thread to ensure proper event delivery
|
|
164
|
-
DispatchQueue.main.async { [weak self] in
|
|
165
|
-
self?.delegate?.httpLocalServerSwifterDidReceiveRequest(requestData)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Wait for JS response or timeout
|
|
169
101
|
let result = semaphore.wait(timeout: .now() + defaultTimeout)
|
|
170
102
|
|
|
171
|
-
// Cleanup
|
|
172
|
-
Self.queue.async {
|
|
173
|
-
Self.pendingResponses.removeValue(forKey: requestId)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Handle timeout
|
|
177
103
|
if result == .timedOut {
|
|
178
|
-
|
|
179
|
-
let timeoutResponse = "{\"error\":\"Request timeout\",\"requestId\":\"\(requestId)\"}"
|
|
180
|
-
return createJsonResponse(timeoutResponse, statusCode: 408)
|
|
104
|
+
return createDynamicResponse("{\"error\":\"timeout\"}", statusCode: 408)
|
|
181
105
|
}
|
|
182
106
|
|
|
183
|
-
|
|
184
|
-
print("✅ HttpLocalServerSwifter: Sending response for requestId: \(requestId)")
|
|
185
|
-
return createJsonResponse(reply)
|
|
107
|
+
return createDynamicResponse(responseString ?? "{\"error\":\"no_response\"}")
|
|
186
108
|
}
|
|
187
109
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return String(bytes: bodyBytes, encoding: .utf8)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private func extractHeaders(from request: HttpRequest) -> [String: String] {
|
|
199
|
-
var headersDict: [String: String] = [:]
|
|
200
|
-
for (key, value) in request.headers {
|
|
201
|
-
headersDict[key] = value
|
|
202
|
-
}
|
|
203
|
-
return headersDict
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
private func extractQuery(from request: HttpRequest) -> [String: String] {
|
|
207
|
-
var queryDict: [String: String] = [:]
|
|
208
|
-
for (key, value) in request.queryParams {
|
|
209
|
-
queryDict[key] = value
|
|
210
|
-
}
|
|
211
|
-
return queryDict
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
private func createJsonResponse(_ body: String, statusCode: Int = 200) -> HttpResponse {
|
|
215
|
-
let headers: [String: String] = [
|
|
110
|
+
/**
|
|
111
|
+
* Extracts status, headers, and body from the JSON string provided by TypeScript
|
|
112
|
+
*/
|
|
113
|
+
private func createDynamicResponse(_ jsonResponse: String, statusCode defaultStatus: Int = 200) -> HttpResponse {
|
|
114
|
+
var finalStatus = defaultStatus
|
|
115
|
+
var finalBody = jsonResponse
|
|
116
|
+
var headers: [String: String] = [
|
|
216
117
|
"Content-Type": "application/json",
|
|
217
118
|
"Access-Control-Allow-Origin": "*",
|
|
218
119
|
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
219
|
-
"Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization",
|
|
220
|
-
"Access-Control-Allow-Credentials": "true",
|
|
120
|
+
"Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization, X-Requested-With",
|
|
221
121
|
"Access-Control-Max-Age": "3600"
|
|
222
122
|
]
|
|
223
123
|
|
|
224
|
-
let
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
124
|
+
if let data = jsonResponse.data(using: .utf8),
|
|
125
|
+
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
|
126
|
+
finalBody = dict["body"] as? String ?? ""
|
|
127
|
+
finalStatus = dict["status"] as? Int ?? 200
|
|
128
|
+
if let customHeaders = dict["headers"] as? [String: String] {
|
|
129
|
+
for (key, value) in customHeaders { headers[key] = value }
|
|
130
|
+
}
|
|
228
131
|
}
|
|
132
|
+
|
|
133
|
+
let bodyData = [UInt8](finalBody.utf8)
|
|
134
|
+
return HttpResponse.raw(finalStatus, "OK", headers) { try $0.write(bodyData) }
|
|
229
135
|
}
|
|
230
136
|
|
|
231
137
|
private func corsResponse() -> HttpResponse {
|
|
232
|
-
|
|
138
|
+
return HttpResponse.raw(204, "No Content", [
|
|
233
139
|
"Access-Control-Allow-Origin": "*",
|
|
234
140
|
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
235
|
-
"Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization",
|
|
236
|
-
"Access-Control-Allow-Credentials": "true",
|
|
141
|
+
"Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization, X-Requested-With",
|
|
237
142
|
"Access-Control-Max-Age": "3600"
|
|
238
|
-
]
|
|
239
|
-
|
|
240
|
-
return HttpResponse.raw(204, "No Content", headers, nil)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
private func errorResponse() -> HttpResponse {
|
|
244
|
-
return createJsonResponse("{\"error\":\"Server error\"}", statusCode: 500)
|
|
143
|
+
], nil)
|
|
245
144
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
switch code {
|
|
249
|
-
case 200: return "OK"
|
|
250
|
-
case 201: return "Created"
|
|
251
|
-
case 202: return "Accepted"
|
|
252
|
-
case 204: return "No Content"
|
|
253
|
-
case 400: return "Bad Request"
|
|
254
|
-
case 401: return "Unauthorized"
|
|
255
|
-
case 403: return "Forbidden"
|
|
256
|
-
case 404: return "Not Found"
|
|
257
|
-
case 408: return "Request Timeout"
|
|
258
|
-
case 500: return "Internal Server Error"
|
|
259
|
-
default: return "Unknown"
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
private func startServer() throws {
|
|
264
|
-
guard let server = webServer else {
|
|
265
|
-
throw NSError(
|
|
266
|
-
domain: "HttpLocalServerSwifter",
|
|
267
|
-
code: -1,
|
|
268
|
-
userInfo: [NSLocalizedDescriptionKey: "WebServer not initialized"]
|
|
269
|
-
)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Try to start on the default port
|
|
273
|
-
do {
|
|
274
|
-
try server.start(defaultPort, forceIPv4: true)
|
|
275
|
-
print("✅ HttpLocalServerSwifter: Server listening on port \(defaultPort)")
|
|
276
|
-
} catch {
|
|
277
|
-
print("❌ HttpLocalServerSwifter: Failed to bind to port \(defaultPort): \(error)")
|
|
278
|
-
throw error
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// MARK: - Network Utilities
|
|
145
|
+
|
|
146
|
+
// WiFi address logic remains the same...
|
|
283
147
|
static func getWiFiAddress() -> String? {
|
|
284
148
|
var address: String?
|
|
285
149
|
var ifaddr: UnsafeMutablePointer<ifaddrs>?
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
guard let interface = ptr?.pointee else { continue }
|
|
301
|
-
|
|
302
|
-
let addrFamily = interface.ifa_addr.pointee.sa_family
|
|
303
|
-
|
|
304
|
-
// Check for IPv4 interface
|
|
305
|
-
guard addrFamily == UInt8(AF_INET) else { continue }
|
|
306
|
-
|
|
307
|
-
let name = String(cString: interface.ifa_name)
|
|
308
|
-
|
|
309
|
-
// WiFi interface (en0) or cellular (pdp_ip0)
|
|
310
|
-
guard name == "en0" || name == "pdp_ip0" else { continue }
|
|
311
|
-
|
|
312
|
-
var addr = interface.ifa_addr.pointee
|
|
313
|
-
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
|
|
314
|
-
|
|
315
|
-
let result = getnameinfo(
|
|
316
|
-
&addr,
|
|
317
|
-
socklen_t(interface.ifa_addr.pointee.sa_len),
|
|
318
|
-
&hostname,
|
|
319
|
-
socklen_t(hostname.count),
|
|
320
|
-
nil,
|
|
321
|
-
0,
|
|
322
|
-
NI_NUMERICHOST
|
|
323
|
-
)
|
|
324
|
-
|
|
325
|
-
guard result == 0 else { continue }
|
|
326
|
-
|
|
327
|
-
address = String(cString: hostname)
|
|
328
|
-
|
|
329
|
-
print("📡 HttpLocalServerSwifter: Found \(name) interface with IP: \(address ?? "unknown")")
|
|
330
|
-
|
|
331
|
-
// Prefer en0 (WiFi) over pdp_ip0 (cellular)
|
|
332
|
-
if name == "en0" {
|
|
333
|
-
break
|
|
150
|
+
if getifaddrs(&ifaddr) == 0 {
|
|
151
|
+
var ptr = ifaddr
|
|
152
|
+
while ptr != nil {
|
|
153
|
+
let interface = ptr!.pointee
|
|
154
|
+
let addrFamily = interface.ifa_addr.pointee.sa_family
|
|
155
|
+
if addrFamily == UInt8(AF_INET) {
|
|
156
|
+
let name = String(cString: interface.ifa_name)
|
|
157
|
+
if name == "en0" {
|
|
158
|
+
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
|
|
159
|
+
getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST)
|
|
160
|
+
address = String(cString: hostname)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
ptr = interface.ifa_next
|
|
334
164
|
}
|
|
165
|
+
freeifaddrs(ifaddr)
|
|
335
166
|
}
|
|
336
|
-
|
|
337
167
|
return address
|
|
338
168
|
}
|
|
339
|
-
}
|
|
169
|
+
}
|
|
@@ -3,7 +3,6 @@ import Capacitor
|
|
|
3
3
|
|
|
4
4
|
@objc(HttpLocalServerSwifterPlugin)
|
|
5
5
|
public class HttpLocalServerSwifterPlugin: CAPPlugin, CAPBridgedPlugin, HttpLocalServerSwifterDelegate {
|
|
6
|
-
// MARK: - CAPBridgedPlugin Properties
|
|
7
6
|
public let identifier = "HttpLocalServerSwifterPlugin"
|
|
8
7
|
public let jsName = "HttpLocalServerSwifter"
|
|
9
8
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -12,59 +11,34 @@ public class HttpLocalServerSwifterPlugin: CAPPlugin, CAPBridgedPlugin, HttpLoca
|
|
|
12
11
|
CAPPluginMethod(name: "sendResponse", returnType: CAPPluginReturnPromise)
|
|
13
12
|
]
|
|
14
13
|
|
|
15
|
-
// MARK: - Properties
|
|
16
14
|
private var localServer: HttpLocalServerSwifter?
|
|
17
15
|
|
|
18
|
-
// MARK: - Lifecycle
|
|
19
|
-
public override func load() {
|
|
20
|
-
print("✅ HttpLocalServerSwifterPlugin: Plugin loaded")
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// MARK: - Plugin Methods
|
|
24
16
|
@objc func connect(_ call: CAPPluginCall) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if localServer == nil {
|
|
28
|
-
localServer = HttpLocalServerSwifter(delegate: self)
|
|
29
|
-
print("✅ HttpLocalServerSwifterPlugin: Server instance created")
|
|
30
|
-
}
|
|
31
|
-
|
|
17
|
+
if localServer == nil { localServer = HttpLocalServerSwifter(delegate: self) }
|
|
32
18
|
localServer?.connect(call)
|
|
33
19
|
}
|
|
34
20
|
|
|
35
21
|
@objc func disconnect(_ call: CAPPluginCall) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if localServer != nil {
|
|
39
|
-
localServer?.disconnect(call)
|
|
40
|
-
localServer = nil
|
|
41
|
-
} else {
|
|
42
|
-
call.resolve()
|
|
43
|
-
}
|
|
22
|
+
localServer?.disconnect(call)
|
|
23
|
+
localServer = nil
|
|
44
24
|
}
|
|
45
25
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
HttpLocalServerSwifter.handleJsResponse(requestId: requestId, body: body)
|
|
61
|
-
call.resolve()
|
|
62
|
-
}
|
|
26
|
+
@objc func sendResponse(_ call: CAPPluginCall) {
|
|
27
|
+
guard let requestId = call.getString("requestId") else {
|
|
28
|
+
call.reject("Missing requestId")
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Cast dictionaryRepresentation explicitly to [String: Any]
|
|
33
|
+
if let responseData = call.dictionaryRepresentation as? [String: Any] {
|
|
34
|
+
HttpLocalServerSwifter.handleJsResponse(requestId: requestId, responseData: responseData)
|
|
35
|
+
call.resolve()
|
|
36
|
+
} else {
|
|
37
|
+
call.reject("Could not parse response data")
|
|
38
|
+
}
|
|
39
|
+
}
|
|
63
40
|
|
|
64
|
-
// MARK: - HttpLocalServerSwifterDelegate
|
|
65
41
|
public func httpLocalServerSwifterDidReceiveRequest(_ data: [String: Any]) {
|
|
66
|
-
print("📨 HttpLocalServerSwifterPlugin: Received request, notifying listeners")
|
|
67
|
-
print(" Request data: \(data)")
|
|
68
42
|
notifyListeners("onRequest", data: data)
|
|
69
43
|
}
|
|
70
|
-
}
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cappitolian/http-local-server-swifter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "Runs a local HTTP server on your device, accessible over LAN. Supports connect, disconnect, GET, and POST methods with IP and port discovery.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|