@cappitolian/http-local-server-swifter 0.0.13 → 0.0.14
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 +70 -247
- package/ios/Sources/HttpLocalServerSwifterPlugin/HttpLocalServerSwifterPlugin.swift +6 -36
- package/package.json +1 -1
|
@@ -2,338 +2,161 @@ 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
|
-
return self?.
|
|
62
|
+
let handler: ((HttpRequest) -> HttpResponse) = { [weak self] request in
|
|
63
|
+
if request.method == "OPTIONS" { return self?.corsResponse() ?? .noContent }
|
|
64
|
+
return self?.processRequest(request) ?? .internalServerError
|
|
92
65
|
}
|
|
93
|
-
|
|
94
|
-
server["/:path"] =
|
|
95
|
-
return self?.handleRequest(request) ?? self?.errorResponse() ?? .internalServerError
|
|
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
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
print("✅ HttpLocalServerSwifter: Handlers configured")
|
|
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()
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return processRequest(request)
|
|
66
|
+
server["/"] = handler
|
|
67
|
+
server["/:path"] = handler
|
|
119
68
|
}
|
|
120
69
|
|
|
121
70
|
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
71
|
let requestId = UUID().uuidString
|
|
129
72
|
var responseString: String?
|
|
130
|
-
|
|
131
|
-
// Setup semaphore for synchronous waiting
|
|
132
73
|
let semaphore = DispatchSemaphore(value: 0)
|
|
133
74
|
|
|
134
75
|
Self.queue.async {
|
|
135
|
-
Self.pendingResponses[requestId] = {
|
|
136
|
-
responseString =
|
|
76
|
+
Self.pendingResponses[requestId] = { jsResponse in
|
|
77
|
+
responseString = jsResponse
|
|
137
78
|
semaphore.signal()
|
|
138
79
|
}
|
|
139
80
|
}
|
|
140
81
|
|
|
141
|
-
//
|
|
142
|
-
|
|
82
|
+
// Map request to dictionary for TS
|
|
83
|
+
let requestData: [String: Any] = [
|
|
143
84
|
"requestId": requestId,
|
|
144
|
-
"method": method,
|
|
145
|
-
"path": path
|
|
85
|
+
"method": request.method,
|
|
86
|
+
"path": request.path,
|
|
87
|
+
"headers": request.headers,
|
|
88
|
+
"query": request.queryParams,
|
|
89
|
+
"body": String(bytes: request.body, encoding: .utf8) ?? ""
|
|
146
90
|
]
|
|
147
91
|
|
|
148
|
-
|
|
149
|
-
if let body = body, !body.isEmpty {
|
|
150
|
-
requestData["body"] = body
|
|
151
|
-
}
|
|
92
|
+
DispatchQueue.main.async { self.delegate?.httpLocalServerSwifterDidReceiveRequest(requestData) }
|
|
152
93
|
|
|
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)")
|
|
162
|
-
|
|
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
94
|
let result = semaphore.wait(timeout: .now() + defaultTimeout)
|
|
170
95
|
|
|
171
|
-
// Cleanup
|
|
172
|
-
Self.queue.async {
|
|
173
|
-
Self.pendingResponses.removeValue(forKey: requestId)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Handle timeout
|
|
177
96
|
if result == .timedOut {
|
|
178
|
-
|
|
179
|
-
let timeoutResponse = "{\"error\":\"Request timeout\",\"requestId\":\"\(requestId)\"}"
|
|
180
|
-
return createJsonResponse(timeoutResponse, statusCode: 408)
|
|
97
|
+
return createDynamicResponse("{\"error\":\"timeout\"}", statusCode: 408)
|
|
181
98
|
}
|
|
182
99
|
|
|
183
|
-
|
|
184
|
-
print("✅ HttpLocalServerSwifter: Sending response for requestId: \(requestId)")
|
|
185
|
-
return createJsonResponse(reply)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private func extractBody(from request: HttpRequest) -> String? {
|
|
189
|
-
let bodyBytes = request.body
|
|
190
|
-
|
|
191
|
-
guard !bodyBytes.isEmpty else {
|
|
192
|
-
return nil
|
|
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
|
|
100
|
+
return createDynamicResponse(responseString ?? "{\"error\":\"no_response\"}")
|
|
212
101
|
}
|
|
213
102
|
|
|
214
|
-
|
|
215
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Extracts status, headers, and body from the JSON string provided by TypeScript
|
|
105
|
+
*/
|
|
106
|
+
private func createDynamicResponse(_ jsonResponse: String, statusCode defaultStatus: Int = 200) -> HttpResponse {
|
|
107
|
+
var finalStatus = defaultStatus
|
|
108
|
+
var finalBody = jsonResponse
|
|
109
|
+
var headers: [String: String] = [
|
|
216
110
|
"Content-Type": "application/json",
|
|
217
111
|
"Access-Control-Allow-Origin": "*",
|
|
218
112
|
"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",
|
|
113
|
+
"Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization, X-Requested-With",
|
|
221
114
|
"Access-Control-Max-Age": "3600"
|
|
222
115
|
]
|
|
223
116
|
|
|
224
|
-
let
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
117
|
+
if let data = jsonResponse.data(using: .utf8),
|
|
118
|
+
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
|
119
|
+
finalBody = dict["body"] as? String ?? ""
|
|
120
|
+
finalStatus = dict["status"] as? Int ?? 200
|
|
121
|
+
if let customHeaders = dict["headers"] as? [String: String] {
|
|
122
|
+
for (key, value) in customHeaders { headers[key] = value }
|
|
123
|
+
}
|
|
228
124
|
}
|
|
125
|
+
|
|
126
|
+
let bodyData = [UInt8](finalBody.utf8)
|
|
127
|
+
return HttpResponse.raw(finalStatus, "OK", headers) { try $0.write(bodyData) }
|
|
229
128
|
}
|
|
230
129
|
|
|
231
130
|
private func corsResponse() -> HttpResponse {
|
|
232
|
-
|
|
131
|
+
return HttpResponse.raw(204, "No Content", [
|
|
233
132
|
"Access-Control-Allow-Origin": "*",
|
|
234
133
|
"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",
|
|
134
|
+
"Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization, X-Requested-With",
|
|
237
135
|
"Access-Control-Max-Age": "3600"
|
|
238
|
-
]
|
|
239
|
-
|
|
240
|
-
return HttpResponse.raw(204, "No Content", headers, nil)
|
|
136
|
+
], nil)
|
|
241
137
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return createJsonResponse("{\"error\":\"Server error\"}", statusCode: 500)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
private func statusDescription(for code: Int) -> String {
|
|
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
|
|
138
|
+
|
|
139
|
+
// WiFi address logic remains the same...
|
|
283
140
|
static func getWiFiAddress() -> String? {
|
|
284
141
|
var address: String?
|
|
285
142
|
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
|
|
143
|
+
if getifaddrs(&ifaddr) == 0 {
|
|
144
|
+
var ptr = ifaddr
|
|
145
|
+
while ptr != nil {
|
|
146
|
+
let interface = ptr!.pointee
|
|
147
|
+
let addrFamily = interface.ifa_addr.pointee.sa_family
|
|
148
|
+
if addrFamily == UInt8(AF_INET) {
|
|
149
|
+
let name = String(cString: interface.ifa_name)
|
|
150
|
+
if name == "en0" {
|
|
151
|
+
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
|
|
152
|
+
getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST)
|
|
153
|
+
address = String(cString: hostname)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
ptr = interface.ifa_next
|
|
334
157
|
}
|
|
158
|
+
freeifaddrs(ifaddr)
|
|
335
159
|
}
|
|
336
|
-
|
|
337
160
|
return address
|
|
338
161
|
}
|
|
339
162
|
}
|
|
@@ -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,30 @@ 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
26
|
@objc func sendResponse(_ call: CAPPluginCall) {
|
|
47
27
|
guard let requestId = call.getString("requestId") else {
|
|
48
|
-
print("❌ HttpLocalServerSwifterPlugin: Missing requestId")
|
|
49
28
|
call.reject("Missing requestId")
|
|
50
29
|
return
|
|
51
30
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
call.reject("Missing body")
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
print("📤 HttpLocalServerSwifterPlugin: sendResponse for requestId: \(requestId)")
|
|
60
|
-
HttpLocalServerSwifter.handleJsResponse(requestId: requestId, body: body)
|
|
31
|
+
// Send the entire JS dictionary to handleJsResponse
|
|
32
|
+
// This includes 'body', 'status', and 'headers'
|
|
33
|
+
HttpLocalServerSwifter.handleJsResponse(requestId: requestId, responseData: call.dictionaryRepresentation)
|
|
61
34
|
call.resolve()
|
|
62
35
|
}
|
|
63
36
|
|
|
64
|
-
// MARK: - HttpLocalServerSwifterDelegate
|
|
65
37
|
public func httpLocalServerSwifterDidReceiveRequest(_ data: [String: Any]) {
|
|
66
|
-
print("📨 HttpLocalServerSwifterPlugin: Received request, notifying listeners")
|
|
67
|
-
print(" Request data: \(data)")
|
|
68
38
|
notifyListeners("onRequest", data: data)
|
|
69
39
|
}
|
|
70
40
|
}
|
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.14",
|
|
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",
|