@cappitolian/http-local-server-swifter 0.0.3 → 0.0.4

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.
@@ -92,7 +92,7 @@ public protocol HttpLocalServerSwifterDelegate: AnyObject {
92
92
  private func setupHandlers() {
93
93
  guard let server = webServer else { return }
94
94
 
95
- // Catch-all handler for all HTTP methods
95
+ // Catch-all handler for all HTTP methods and paths
96
96
  server["/(.*)"] = { [weak self] request in
97
97
  guard let self = self else {
98
98
  return self?.errorResponse() ?? .internalServerError
@@ -168,7 +168,8 @@ public protocol HttpLocalServerSwifterDelegate: AnyObject {
168
168
  }
169
169
 
170
170
  private func extractBody(from request: HttpRequest) -> String? {
171
- guard let bodyBytes = request.body else {
171
+ guard let bodyBytes = request.body,
172
+ !bodyBytes.isEmpty else {
172
173
  return nil
173
174
  }
174
175
 
@@ -176,7 +177,8 @@ public protocol HttpLocalServerSwifterDelegate: AnyObject {
176
177
  }
177
178
 
178
179
  private func extractHeaders(from request: HttpRequest) -> [String: String] {
179
- return request.headers
180
+ // Swifter's headers is [(String, String)]
181
+ return Dictionary(uniqueKeysWithValues: request.headers)
180
182
  }
181
183
 
182
184
  private func extractQuery(from request: HttpRequest) -> [String: String] {
@@ -184,44 +186,54 @@ public protocol HttpLocalServerSwifterDelegate: AnyObject {
184
186
  }
185
187
 
186
188
  private func createJsonResponse(_ body: String, statusCode: Int = 200) -> HttpResponse {
187
- var response: HttpResponse
188
-
189
- switch statusCode {
190
- case 200:
191
- response = .ok(.text(body))
192
- case 204:
193
- response = HttpResponse.raw(204, "No Content", [:], nil)
194
- case 408:
195
- response = HttpResponse.raw(408, "Request Timeout", [:], { writer in
196
- try writer.write([UInt8](body.utf8))
197
- })
198
- case 500:
199
- response = .internalServerError
200
- default:
201
- response = HttpResponse.raw(statusCode, "Custom Status", [:], { writer in
202
- try writer.write([UInt8](body.utf8))
203
- })
204
- }
205
-
206
- // Add CORS headers
207
- return response.withHeaders([
189
+ let headers: [String: String] = [
208
190
  "Content-Type": "application/json",
209
191
  "Access-Control-Allow-Origin": "*",
210
192
  "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
211
193
  "Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization",
212
194
  "Access-Control-Allow-Credentials": "true",
213
195
  "Access-Control-Max-Age": "3600"
214
- ])
196
+ ]
197
+
198
+ let bodyData = [UInt8](body.utf8)
199
+
200
+ return HttpResponse.raw(statusCode, statusDescription(for: statusCode), headers) { writer in
201
+ try writer.write(bodyData)
202
+ }
215
203
  }
216
204
 
217
205
  private func corsResponse() -> HttpResponse {
218
- return createJsonResponse("{}", statusCode: 204)
206
+ let headers: [String: String] = [
207
+ "Access-Control-Allow-Origin": "*",
208
+ "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
209
+ "Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization",
210
+ "Access-Control-Allow-Credentials": "true",
211
+ "Access-Control-Max-Age": "3600"
212
+ ]
213
+
214
+ return HttpResponse.raw(204, "No Content", headers, nil)
219
215
  }
220
216
 
221
217
  private func errorResponse() -> HttpResponse {
222
218
  return createJsonResponse("{\"error\":\"Server error\"}", statusCode: 500)
223
219
  }
224
220
 
221
+ private func statusDescription(for code: Int) -> String {
222
+ switch code {
223
+ case 200: return "OK"
224
+ case 201: return "Created"
225
+ case 202: return "Accepted"
226
+ case 204: return "No Content"
227
+ case 400: return "Bad Request"
228
+ case 401: return "Unauthorized"
229
+ case 403: return "Forbidden"
230
+ case 404: return "Not Found"
231
+ case 408: return "Request Timeout"
232
+ case 500: return "Internal Server Error"
233
+ default: return "Unknown"
234
+ }
235
+ }
236
+
225
237
  private func startServer() throws {
226
238
  guard let server = webServer else {
227
239
  throw NSError(
@@ -289,118 +301,4 @@ public protocol HttpLocalServerSwifterDelegate: AnyObject {
289
301
 
290
302
  return address
291
303
  }
292
- }
293
-
294
- // MARK: - HttpResponse Extension
295
- extension HttpResponse {
296
- func withHeaders(_ headers: [String: String]) -> HttpResponse {
297
- return HttpResponse.raw(self.statusCode(), self.reasonPhrase(), headers, { writer in
298
- if let bodyData = try? self.content() {
299
- try writer.write(bodyData)
300
- }
301
- })
302
- }
303
-
304
- func statusCode() -> Int {
305
- switch self {
306
- case .ok: return 200
307
- case .created: return 201
308
- case .accepted: return 202
309
- case .movedPermanently: return 301
310
- case .notModified: return 304
311
- case .badRequest: return 400
312
- case .unauthorized: return 401
313
- case .forbidden: return 403
314
- case .notFound: return 404
315
- case .internalServerError: return 500
316
- case .raw(let code, _, _, _): return code
317
- default: return 200
318
- }
319
- }
320
-
321
- func reasonPhrase() -> String {
322
- switch self {
323
- case .ok: return "OK"
324
- case .created: return "Created"
325
- case .accepted: return "Accepted"
326
- case .movedPermanently: return "Moved Permanently"
327
- case .notModified: return "Not Modified"
328
- case .badRequest: return "Bad Request"
329
- case .unauthorized: return "Unauthorized"
330
- case .forbidden: return "Forbidden"
331
- case .notFound: return "Not Found"
332
- case .internalServerError: return "Internal Server Error"
333
- case .raw(_, let phrase, _, _): return phrase
334
- default: return "OK"
335
- }
336
- }
337
-
338
- func content() throws -> [UInt8] {
339
- switch self {
340
- case .ok(let body), .created(let body), .accepted(let body):
341
- return try bodyToBytes(body)
342
- case .badRequest(let body), .notFound(let body), .internalServerError:
343
- if let body = body {
344
- return try bodyToBytes(body)
345
- }
346
- return []
347
- case .raw(_, _, _, let writer):
348
- var data = [UInt8]()
349
- let mockWriter = MockResponseWriter { bytes in
350
- data.append(contentsOf: bytes)
351
- }
352
- try writer?(mockWriter)
353
- return data
354
- default:
355
- return []
356
- }
357
- }
358
-
359
- private func bodyToBytes(_ body: HttpResponseBody) throws -> [UInt8] {
360
- switch body {
361
- case .text(let string):
362
- return [UInt8](string.utf8)
363
- case .html(let string):
364
- return [UInt8](string.utf8)
365
- case .json(let object):
366
- let data = try JSONSerialization.data(withJSONObject: object)
367
- return [UInt8](data)
368
- case .data(let data, _):
369
- return [UInt8](data)
370
- case .custom(let writer):
371
- var bytes = [UInt8]()
372
- let mockWriter = MockResponseWriter { data in
373
- bytes.append(contentsOf: data)
374
- }
375
- try writer(mockWriter)
376
- return bytes
377
- }
378
- }
379
- }
380
-
381
- // MARK: - Mock Response Writer
382
- private class MockResponseWriter: HttpResponseBodyWriter {
383
- let writeHandler: ([UInt8]) -> Void
384
-
385
- init(writeHandler: @escaping ([UInt8]) -> Void) {
386
- self.writeHandler = writeHandler
387
- }
388
-
389
- func write(_ data: [UInt8]) throws {
390
- writeHandler(data)
391
- }
392
-
393
- func write(_ data: ArraySlice<UInt8>) throws {
394
- writeHandler(Array(data))
395
- }
396
-
397
- func write(_ data: NSData) throws {
398
- var bytes = [UInt8](repeating: 0, count: data.length)
399
- data.getBytes(&bytes, length: data.length)
400
- writeHandler(bytes)
401
- }
402
-
403
- func write(_ data: Data) throws {
404
- writeHandler([UInt8](data))
405
- }
406
304
  }
@@ -7,7 +7,7 @@ import Capacitor
7
7
  */
8
8
  @objc(HttpLocalServerSwifterPlugin)
9
9
  public class HttpLocalServerSwifterPlugin: CAPPlugin, CAPBridgedPlugin, HttpLocalServerSwifterDelegate {
10
-
10
+ // MARK: - CAPBridgedPlugin Properties
11
11
  public let identifier = "HttpLocalServerSwifterPlugin"
12
12
  public let jsName = "HttpLocalServerSwifter"
13
13
  public let pluginMethods: [CAPPluginMethod] = [
@@ -16,8 +16,11 @@ public class HttpLocalServerSwifterPlugin: CAPPlugin, CAPBridgedPlugin, HttpLoca
16
16
  CAPPluginMethod(name: "sendResponse", returnType: CAPPluginReturnPromise)
17
17
  ]
18
18
 
19
+ // MARK: - Properties
19
20
  private var localServer: HttpLocalServerSwifter?
20
21
 
22
+ // MARK: - Plugin Methods
23
+
21
24
  /**
22
25
  * Starts the local HTTP server.
23
26
  * @return ip: The server's IP address
@@ -62,6 +65,12 @@ public class HttpLocalServerSwifterPlugin: CAPPlugin, CAPBridgedPlugin, HttpLoca
62
65
  call.resolve()
63
66
  }
64
67
 
68
+ // MARK: - HttpLocalServerSwifterDelegate
69
+
70
+ /**
71
+ * Delegate method called when the server receives an HTTP request.
72
+ * Notifies JavaScript via the 'onRequest' event.
73
+ */
65
74
  public func httpLocalServerSwifterDidReceiveRequest(_ data: [String: Any]) {
66
75
  notifyListeners("onRequest", data: data)
67
76
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cappitolian/http-local-server-swifter",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
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",