@cappitolian/http-local-server-swifter 0.0.1
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/CappitolianHttpLocalServerSwifter.podspec +18 -0
- package/Package.swift +30 -0
- package/README.md +135 -0
- package/android/build.gradle +58 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/cappitolian/plugins/httplocalserviceswifter/HttpLocalServerSwifter.java +365 -0
- package/android/src/main/java/com/cappitolian/plugins/httplocalserviceswifter/HttpLocalServerSwifterPlugin.java +80 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +312 -0
- package/dist/esm/definitions.d.ts +170 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +33 -0
- package/dist/esm/index.js +36 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +14 -0
- package/dist/esm/web.js +49 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +92 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +95 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/HttpLocalServerSwifterPlugin/HttpLocalServerSwifter.swift +406 -0
- package/ios/Sources/HttpLocalServerSwifterPlugin/HttpLocalServerSwifterPlugin.swift +68 -0
- package/ios/Tests/HttpLocalServerSwifterPluginTests/HttpLocalServerSwifterTests.swift +15 -0
- package/package.json +80 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Plugin de servidor HTTP local para Android e iOS.
|
|
7
|
+
*
|
|
8
|
+
* Permite crear un servidor HTTP en el dispositivo que puede recibir
|
|
9
|
+
* peticiones desde otros dispositivos en la misma red local.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { HttpLocalServerSwifter } from '@cappitolian/http-local-server-swifter';
|
|
14
|
+
*
|
|
15
|
+
* // Iniciar servidor
|
|
16
|
+
* const { ip, port } = await HttpLocalServerSwifter.connect();
|
|
17
|
+
* console.log(`Servidor en http://${ip}:${port}`);
|
|
18
|
+
*
|
|
19
|
+
* // Escuchar peticiones
|
|
20
|
+
* await HttpLocalServerSwifter.addListener('onRequest', async (data) => {
|
|
21
|
+
* console.log('Petición recibida:', data);
|
|
22
|
+
*
|
|
23
|
+
* // Procesar y responder
|
|
24
|
+
* await HttpLocalServerSwifter.sendResponse({
|
|
25
|
+
* requestId: data.requestId,
|
|
26
|
+
* body: JSON.stringify({ success: true })
|
|
27
|
+
* });
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Detener servidor
|
|
31
|
+
* await HttpLocalServerSwifter.disconnect();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
const HttpLocalServerSwifter = core.registerPlugin('HttpLocalServerSwifter', {
|
|
35
|
+
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.HttpLocalServerSwifterWeb()),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Implementación web (mock) del plugin HttpLocalServerSwifter.
|
|
40
|
+
*
|
|
41
|
+
* Proporciona funcionalidad simulada para desarrollo en navegador.
|
|
42
|
+
* El servidor real solo funciona en dispositivos iOS/Android nativos.
|
|
43
|
+
*/
|
|
44
|
+
class HttpLocalServerSwifterWeb extends core.WebPlugin {
|
|
45
|
+
constructor() {
|
|
46
|
+
super(...arguments);
|
|
47
|
+
this.isRunning = false;
|
|
48
|
+
}
|
|
49
|
+
async connect() {
|
|
50
|
+
if (this.isRunning) {
|
|
51
|
+
console.warn('[HttpLocalServerSwifter Web] El servidor ya está ejecutándose (Mock).');
|
|
52
|
+
return { ip: '127.0.0.1', port: 8080 };
|
|
53
|
+
}
|
|
54
|
+
console.warn('[HttpLocalServerSwifter Web] El servidor HTTP nativo no está disponible en navegador.\n' +
|
|
55
|
+
'Retornando valores mock para desarrollo.\n' +
|
|
56
|
+
'Para funcionalidad real, ejecuta en un dispositivo iOS/Android.');
|
|
57
|
+
this.isRunning = true;
|
|
58
|
+
return {
|
|
59
|
+
ip: '127.0.0.1',
|
|
60
|
+
port: 8080
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async disconnect() {
|
|
64
|
+
if (!this.isRunning) {
|
|
65
|
+
console.log('[HttpLocalServerSwifter Web] El servidor ya está detenido (Mock).');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.log('[HttpLocalServerSwifter Web] Servidor detenido (Mock).');
|
|
69
|
+
this.isRunning = false;
|
|
70
|
+
}
|
|
71
|
+
async sendResponse(options) {
|
|
72
|
+
if (!this.isRunning) {
|
|
73
|
+
throw new Error('Server is not running. Call connect() first.');
|
|
74
|
+
}
|
|
75
|
+
const { requestId, body } = options;
|
|
76
|
+
if (!requestId) {
|
|
77
|
+
throw new Error('Missing requestId');
|
|
78
|
+
}
|
|
79
|
+
if (!body) {
|
|
80
|
+
throw new Error('Missing body');
|
|
81
|
+
}
|
|
82
|
+
console.log(`[HttpLocalServerSwifter Web] Mock response sent for requestId: ${requestId}`, '\nBody preview:', body.substring(0, 100) + (body.length > 100 ? '...' : ''));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
87
|
+
__proto__: null,
|
|
88
|
+
HttpLocalServerSwifterWeb: HttpLocalServerSwifterWeb
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
exports.HttpLocalServerSwifter = HttpLocalServerSwifter;
|
|
92
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\n/**\n * Plugin de servidor HTTP local para Android e iOS.\n *\n * Permite crear un servidor HTTP en el dispositivo que puede recibir\n * peticiones desde otros dispositivos en la misma red local.\n *\n * @example\n * ```typescript\n * import { HttpLocalServerSwifter } from '@cappitolian/http-local-server-swifter';\n *\n * // Iniciar servidor\n * const { ip, port } = await HttpLocalServerSwifter.connect();\n * console.log(`Servidor en http://${ip}:${port}`);\n *\n * // Escuchar peticiones\n * await HttpLocalServerSwifter.addListener('onRequest', async (data) => {\n * console.log('Petición recibida:', data);\n *\n * // Procesar y responder\n * await HttpLocalServerSwifter.sendResponse({\n * requestId: data.requestId,\n * body: JSON.stringify({ success: true })\n * });\n * });\n *\n * // Detener servidor\n * await HttpLocalServerSwifter.disconnect();\n * ```\n */\nconst HttpLocalServerSwifter = registerPlugin('HttpLocalServerSwifter', {\n web: () => import('./web').then(m => new m.HttpLocalServerSwifterWeb()),\n});\nexport * from './definitions';\nexport { HttpLocalServerSwifter };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\n/**\n * Implementación web (mock) del plugin HttpLocalServerSwifter.\n *\n * Proporciona funcionalidad simulada para desarrollo en navegador.\n * El servidor real solo funciona en dispositivos iOS/Android nativos.\n */\nexport class HttpLocalServerSwifterWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.isRunning = false;\n }\n async connect() {\n if (this.isRunning) {\n console.warn('[HttpLocalServerSwifter Web] El servidor ya está ejecutándose (Mock).');\n return { ip: '127.0.0.1', port: 8080 };\n }\n console.warn('[HttpLocalServerSwifter Web] El servidor HTTP nativo no está disponible en navegador.\\n' +\n 'Retornando valores mock para desarrollo.\\n' +\n 'Para funcionalidad real, ejecuta en un dispositivo iOS/Android.');\n this.isRunning = true;\n return {\n ip: '127.0.0.1',\n port: 8080\n };\n }\n async disconnect() {\n if (!this.isRunning) {\n console.log('[HttpLocalServerSwifter Web] El servidor ya está detenido (Mock).');\n return;\n }\n console.log('[HttpLocalServerSwifter Web] Servidor detenido (Mock).');\n this.isRunning = false;\n }\n async sendResponse(options) {\n if (!this.isRunning) {\n throw new Error('Server is not running. Call connect() first.');\n }\n const { requestId, body } = options;\n if (!requestId) {\n throw new Error('Missing requestId');\n }\n if (!body) {\n throw new Error('Missing body');\n }\n console.log(`[HttpLocalServerSwifter Web] Mock response sent for requestId: ${requestId}`, '\\nBody preview:', body.substring(0, 100) + (body.length > 100 ? '...' : ''));\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACK,MAAC,sBAAsB,GAAGA,mBAAc,CAAC,wBAAwB,EAAE;AACxE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,yBAAyB,EAAE,CAAC;AAC3E,CAAC;;AC/BD;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,yBAAyB,SAASC,cAAS,CAAC;AACzD,IAAI,WAAW,GAAG;AAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;AAC3B,QAAQ,IAAI,CAAC,SAAS,GAAG,KAAK;AAC9B,IAAI;AACJ,IAAI,MAAM,OAAO,GAAG;AACpB,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;AAC5B,YAAY,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC;AACjG,YAAY,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;AAClD,QAAQ;AACR,QAAQ,OAAO,CAAC,IAAI,CAAC,yFAAyF;AAC9G,YAAY,4CAA4C;AACxD,YAAY,iEAAiE,CAAC;AAC9E,QAAQ,IAAI,CAAC,SAAS,GAAG,IAAI;AAC7B,QAAQ,OAAO;AACf,YAAY,EAAE,EAAE,WAAW;AAC3B,YAAY,IAAI,EAAE;AAClB,SAAS;AACT,IAAI;AACJ,IAAI,MAAM,UAAU,GAAG;AACvB,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;AAC7B,YAAY,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC;AAC5F,YAAY;AACZ,QAAQ;AACR,QAAQ,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC;AAC7E,QAAQ,IAAI,CAAC,SAAS,GAAG,KAAK;AAC9B,IAAI;AACJ,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;AAChC,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;AAC7B,YAAY,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC;AAC3E,QAAQ;AACR,QAAQ,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO;AAC3C,QAAQ,IAAI,CAAC,SAAS,EAAE;AACxB,YAAY,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC;AAChD,QAAQ;AACR,QAAQ,IAAI,CAAC,IAAI,EAAE;AACnB,YAAY,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC;AAC3C,QAAQ;AACR,QAAQ,OAAO,CAAC,GAAG,CAAC,CAAC,+DAA+D,EAAE,SAAS,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;AAChL,IAAI;AACJ;;;;;;;;;"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
var capacitorHttpLocalServerSwifter = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Plugin de servidor HTTP local para Android e iOS.
|
|
6
|
+
*
|
|
7
|
+
* Permite crear un servidor HTTP en el dispositivo que puede recibir
|
|
8
|
+
* peticiones desde otros dispositivos en la misma red local.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { HttpLocalServerSwifter } from '@cappitolian/http-local-server-swifter';
|
|
13
|
+
*
|
|
14
|
+
* // Iniciar servidor
|
|
15
|
+
* const { ip, port } = await HttpLocalServerSwifter.connect();
|
|
16
|
+
* console.log(`Servidor en http://${ip}:${port}`);
|
|
17
|
+
*
|
|
18
|
+
* // Escuchar peticiones
|
|
19
|
+
* await HttpLocalServerSwifter.addListener('onRequest', async (data) => {
|
|
20
|
+
* console.log('Petición recibida:', data);
|
|
21
|
+
*
|
|
22
|
+
* // Procesar y responder
|
|
23
|
+
* await HttpLocalServerSwifter.sendResponse({
|
|
24
|
+
* requestId: data.requestId,
|
|
25
|
+
* body: JSON.stringify({ success: true })
|
|
26
|
+
* });
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Detener servidor
|
|
30
|
+
* await HttpLocalServerSwifter.disconnect();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
const HttpLocalServerSwifter = core.registerPlugin('HttpLocalServerSwifter', {
|
|
34
|
+
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.HttpLocalServerSwifterWeb()),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Implementación web (mock) del plugin HttpLocalServerSwifter.
|
|
39
|
+
*
|
|
40
|
+
* Proporciona funcionalidad simulada para desarrollo en navegador.
|
|
41
|
+
* El servidor real solo funciona en dispositivos iOS/Android nativos.
|
|
42
|
+
*/
|
|
43
|
+
class HttpLocalServerSwifterWeb extends core.WebPlugin {
|
|
44
|
+
constructor() {
|
|
45
|
+
super(...arguments);
|
|
46
|
+
this.isRunning = false;
|
|
47
|
+
}
|
|
48
|
+
async connect() {
|
|
49
|
+
if (this.isRunning) {
|
|
50
|
+
console.warn('[HttpLocalServerSwifter Web] El servidor ya está ejecutándose (Mock).');
|
|
51
|
+
return { ip: '127.0.0.1', port: 8080 };
|
|
52
|
+
}
|
|
53
|
+
console.warn('[HttpLocalServerSwifter Web] El servidor HTTP nativo no está disponible en navegador.\n' +
|
|
54
|
+
'Retornando valores mock para desarrollo.\n' +
|
|
55
|
+
'Para funcionalidad real, ejecuta en un dispositivo iOS/Android.');
|
|
56
|
+
this.isRunning = true;
|
|
57
|
+
return {
|
|
58
|
+
ip: '127.0.0.1',
|
|
59
|
+
port: 8080
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async disconnect() {
|
|
63
|
+
if (!this.isRunning) {
|
|
64
|
+
console.log('[HttpLocalServerSwifter Web] El servidor ya está detenido (Mock).');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.log('[HttpLocalServerSwifter Web] Servidor detenido (Mock).');
|
|
68
|
+
this.isRunning = false;
|
|
69
|
+
}
|
|
70
|
+
async sendResponse(options) {
|
|
71
|
+
if (!this.isRunning) {
|
|
72
|
+
throw new Error('Server is not running. Call connect() first.');
|
|
73
|
+
}
|
|
74
|
+
const { requestId, body } = options;
|
|
75
|
+
if (!requestId) {
|
|
76
|
+
throw new Error('Missing requestId');
|
|
77
|
+
}
|
|
78
|
+
if (!body) {
|
|
79
|
+
throw new Error('Missing body');
|
|
80
|
+
}
|
|
81
|
+
console.log(`[HttpLocalServerSwifter Web] Mock response sent for requestId: ${requestId}`, '\nBody preview:', body.substring(0, 100) + (body.length > 100 ? '...' : ''));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
86
|
+
__proto__: null,
|
|
87
|
+
HttpLocalServerSwifterWeb: HttpLocalServerSwifterWeb
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
exports.HttpLocalServerSwifter = HttpLocalServerSwifter;
|
|
91
|
+
|
|
92
|
+
return exports;
|
|
93
|
+
|
|
94
|
+
})({}, capacitorExports);
|
|
95
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\n/**\n * Plugin de servidor HTTP local para Android e iOS.\n *\n * Permite crear un servidor HTTP en el dispositivo que puede recibir\n * peticiones desde otros dispositivos en la misma red local.\n *\n * @example\n * ```typescript\n * import { HttpLocalServerSwifter } from '@cappitolian/http-local-server-swifter';\n *\n * // Iniciar servidor\n * const { ip, port } = await HttpLocalServerSwifter.connect();\n * console.log(`Servidor en http://${ip}:${port}`);\n *\n * // Escuchar peticiones\n * await HttpLocalServerSwifter.addListener('onRequest', async (data) => {\n * console.log('Petición recibida:', data);\n *\n * // Procesar y responder\n * await HttpLocalServerSwifter.sendResponse({\n * requestId: data.requestId,\n * body: JSON.stringify({ success: true })\n * });\n * });\n *\n * // Detener servidor\n * await HttpLocalServerSwifter.disconnect();\n * ```\n */\nconst HttpLocalServerSwifter = registerPlugin('HttpLocalServerSwifter', {\n web: () => import('./web').then(m => new m.HttpLocalServerSwifterWeb()),\n});\nexport * from './definitions';\nexport { HttpLocalServerSwifter };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\n/**\n * Implementación web (mock) del plugin HttpLocalServerSwifter.\n *\n * Proporciona funcionalidad simulada para desarrollo en navegador.\n * El servidor real solo funciona en dispositivos iOS/Android nativos.\n */\nexport class HttpLocalServerSwifterWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.isRunning = false;\n }\n async connect() {\n if (this.isRunning) {\n console.warn('[HttpLocalServerSwifter Web] El servidor ya está ejecutándose (Mock).');\n return { ip: '127.0.0.1', port: 8080 };\n }\n console.warn('[HttpLocalServerSwifter Web] El servidor HTTP nativo no está disponible en navegador.\\n' +\n 'Retornando valores mock para desarrollo.\\n' +\n 'Para funcionalidad real, ejecuta en un dispositivo iOS/Android.');\n this.isRunning = true;\n return {\n ip: '127.0.0.1',\n port: 8080\n };\n }\n async disconnect() {\n if (!this.isRunning) {\n console.log('[HttpLocalServerSwifter Web] El servidor ya está detenido (Mock).');\n return;\n }\n console.log('[HttpLocalServerSwifter Web] Servidor detenido (Mock).');\n this.isRunning = false;\n }\n async sendResponse(options) {\n if (!this.isRunning) {\n throw new Error('Server is not running. Call connect() first.');\n }\n const { requestId, body } = options;\n if (!requestId) {\n throw new Error('Missing requestId');\n }\n if (!body) {\n throw new Error('Missing body');\n }\n console.log(`[HttpLocalServerSwifter Web] Mock response sent for requestId: ${requestId}`, '\\nBody preview:', body.substring(0, 100) + (body.length > 100 ? '...' : ''));\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,sBAAsB,GAAGA,mBAAc,CAAC,wBAAwB,EAAE;IACxE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,yBAAyB,EAAE,CAAC;IAC3E,CAAC;;IC/BD;IACA;IACA;IACA;IACA;IACA;IACO,MAAM,yBAAyB,SAASC,cAAS,CAAC;IACzD,IAAI,WAAW,GAAG;IAClB,QAAQ,KAAK,CAAC,GAAG,SAAS,CAAC;IAC3B,QAAQ,IAAI,CAAC,SAAS,GAAG,KAAK;IAC9B,IAAI;IACJ,IAAI,MAAM,OAAO,GAAG;IACpB,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;IAC5B,YAAY,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC;IACjG,YAAY,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;IAClD,QAAQ;IACR,QAAQ,OAAO,CAAC,IAAI,CAAC,yFAAyF;IAC9G,YAAY,4CAA4C;IACxD,YAAY,iEAAiE,CAAC;IAC9E,QAAQ,IAAI,CAAC,SAAS,GAAG,IAAI;IAC7B,QAAQ,OAAO;IACf,YAAY,EAAE,EAAE,WAAW;IAC3B,YAAY,IAAI,EAAE;IAClB,SAAS;IACT,IAAI;IACJ,IAAI,MAAM,UAAU,GAAG;IACvB,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;IAC7B,YAAY,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC;IAC5F,YAAY;IACZ,QAAQ;IACR,QAAQ,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC;IAC7E,QAAQ,IAAI,CAAC,SAAS,GAAG,KAAK;IAC9B,IAAI;IACJ,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;IAChC,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;IAC7B,YAAY,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC;IAC3E,QAAQ;IACR,QAAQ,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO;IAC3C,QAAQ,IAAI,CAAC,SAAS,EAAE;IACxB,YAAY,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC;IAChD,QAAQ;IACR,QAAQ,IAAI,CAAC,IAAI,EAAE;IACnB,YAAY,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC;IAC3C,QAAQ;IACR,QAAQ,OAAO,CAAC,GAAG,CAAC,CAAC,+DAA+D,EAAE,SAAS,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;IAChL,IAAI;IACJ;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Swifter
|
|
3
|
+
import Capacitor
|
|
4
|
+
|
|
5
|
+
// MARK: - Protocol
|
|
6
|
+
public protocol HttpLocalServerSwifterDelegate: AnyObject {
|
|
7
|
+
func httpLocalServerSwifterDidReceiveRequest(_ data: [String: Any])
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// MARK: - HttpLocalServerSwifter
|
|
11
|
+
@objc public class HttpLocalServerSwifter: NSObject {
|
|
12
|
+
// MARK: - Properties
|
|
13
|
+
private var webServer: HttpServer?
|
|
14
|
+
private weak var delegate: HttpLocalServerSwifterDelegate?
|
|
15
|
+
|
|
16
|
+
private static var pendingResponses = [String: (String) -> Void]()
|
|
17
|
+
private static let queue = DispatchQueue(label: "com.cappitolian.HttpLocalServerSwifter.pendingResponses", qos: .userInitiated)
|
|
18
|
+
|
|
19
|
+
private let defaultTimeout: TimeInterval = 5.0
|
|
20
|
+
private let defaultPort: UInt16 = 8080
|
|
21
|
+
|
|
22
|
+
// MARK: - Initialization
|
|
23
|
+
public init(delegate: HttpLocalServerSwifterDelegate) {
|
|
24
|
+
self.delegate = delegate
|
|
25
|
+
super.init()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
deinit {
|
|
29
|
+
disconnect()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// MARK: - Public Methods
|
|
33
|
+
@objc public func connect(_ call: CAPPluginCall) {
|
|
34
|
+
DispatchQueue.main.async { [weak self] in
|
|
35
|
+
guard let self = self else {
|
|
36
|
+
call.reject("Server instance deallocated")
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Stop existing server if running
|
|
41
|
+
self.disconnect()
|
|
42
|
+
|
|
43
|
+
self.webServer = HttpServer()
|
|
44
|
+
self.setupHandlers()
|
|
45
|
+
|
|
46
|
+
do {
|
|
47
|
+
try self.startServer()
|
|
48
|
+
let ip = Self.getWiFiAddress() ?? "127.0.0.1"
|
|
49
|
+
call.resolve([
|
|
50
|
+
"ip": ip,
|
|
51
|
+
"port": self.defaultPort
|
|
52
|
+
])
|
|
53
|
+
} catch {
|
|
54
|
+
call.reject("Failed to start server: \(error.localizedDescription)")
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc public func disconnect(_ call: CAPPluginCall? = nil) {
|
|
60
|
+
DispatchQueue.main.async { [weak self] in
|
|
61
|
+
guard let self = self else {
|
|
62
|
+
call?.reject("Server instance deallocated")
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
self.disconnect()
|
|
67
|
+
call?.resolve()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// MARK: - Static Methods
|
|
72
|
+
static func handleJsResponse(requestId: String, body: String) {
|
|
73
|
+
queue.async {
|
|
74
|
+
if let callback = pendingResponses[requestId] {
|
|
75
|
+
callback(body)
|
|
76
|
+
pendingResponses.removeValue(forKey: requestId)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// MARK: - Private Methods
|
|
82
|
+
private func disconnect() {
|
|
83
|
+
webServer?.stop()
|
|
84
|
+
webServer = nil
|
|
85
|
+
|
|
86
|
+
// Clear pending responses
|
|
87
|
+
Self.queue.async {
|
|
88
|
+
Self.pendingResponses.removeAll()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private func setupHandlers() {
|
|
93
|
+
guard let server = webServer else { return }
|
|
94
|
+
|
|
95
|
+
// Catch-all handler for all HTTP methods
|
|
96
|
+
server["/(.*)"] = { [weak self] request in
|
|
97
|
+
guard let self = self else {
|
|
98
|
+
return self?.errorResponse() ?? .internalServerError
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Handle OPTIONS (CORS preflight)
|
|
102
|
+
if request.method == "OPTIONS" {
|
|
103
|
+
return self.corsResponse()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return self.processRequest(request)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private func processRequest(_ request: HttpRequest) -> HttpResponse {
|
|
111
|
+
let method = request.method
|
|
112
|
+
let path = request.path
|
|
113
|
+
let body = extractBody(from: request)
|
|
114
|
+
let headers = extractHeaders(from: request)
|
|
115
|
+
let query = extractQuery(from: request)
|
|
116
|
+
|
|
117
|
+
let requestId = UUID().uuidString
|
|
118
|
+
var responseString: String?
|
|
119
|
+
|
|
120
|
+
// Setup semaphore for synchronous waiting
|
|
121
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
122
|
+
|
|
123
|
+
Self.queue.async {
|
|
124
|
+
Self.pendingResponses[requestId] = { responseBody in
|
|
125
|
+
responseString = responseBody
|
|
126
|
+
semaphore.signal()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Notify delegate with request info
|
|
131
|
+
var requestData: [String: Any] = [
|
|
132
|
+
"requestId": requestId,
|
|
133
|
+
"method": method,
|
|
134
|
+
"path": path
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
// Only add if they exist (consistent with TypeScript and Android)
|
|
138
|
+
if let body = body, !body.isEmpty {
|
|
139
|
+
requestData["body"] = body
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if !headers.isEmpty {
|
|
143
|
+
requestData["headers"] = headers
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if !query.isEmpty {
|
|
147
|
+
requestData["query"] = query
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
delegate?.httpLocalServerSwifterDidReceiveRequest(requestData)
|
|
151
|
+
|
|
152
|
+
// Wait for JS response or timeout
|
|
153
|
+
let result = semaphore.wait(timeout: .now() + defaultTimeout)
|
|
154
|
+
|
|
155
|
+
// Cleanup
|
|
156
|
+
Self.queue.async {
|
|
157
|
+
Self.pendingResponses.removeValue(forKey: requestId)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Handle timeout
|
|
161
|
+
if result == .timedOut {
|
|
162
|
+
let timeoutResponse = "{\"error\":\"Request timeout\",\"requestId\":\"\(requestId)\"}"
|
|
163
|
+
return createJsonResponse(timeoutResponse, statusCode: 408)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let reply = responseString ?? "{\"error\":\"No response from handler\"}"
|
|
167
|
+
return createJsonResponse(reply)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private func extractBody(from request: HttpRequest) -> String? {
|
|
171
|
+
guard let bodyBytes = request.body else {
|
|
172
|
+
return nil
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return String(bytes: bodyBytes, encoding: .utf8)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private func extractHeaders(from request: HttpRequest) -> [String: String] {
|
|
179
|
+
return request.headers
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private func extractQuery(from request: HttpRequest) -> [String: String] {
|
|
183
|
+
return request.queryParams
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
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([
|
|
208
|
+
"Content-Type": "application/json",
|
|
209
|
+
"Access-Control-Allow-Origin": "*",
|
|
210
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
211
|
+
"Access-Control-Allow-Headers": "Origin, Content-Type, Accept, Authorization",
|
|
212
|
+
"Access-Control-Allow-Credentials": "true",
|
|
213
|
+
"Access-Control-Max-Age": "3600"
|
|
214
|
+
])
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private func corsResponse() -> HttpResponse {
|
|
218
|
+
return createJsonResponse("{}", statusCode: 204)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private func errorResponse() -> HttpResponse {
|
|
222
|
+
return createJsonResponse("{\"error\":\"Server error\"}", statusCode: 500)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private func startServer() throws {
|
|
226
|
+
guard let server = webServer else {
|
|
227
|
+
throw NSError(
|
|
228
|
+
domain: "HttpLocalServerSwifter",
|
|
229
|
+
code: -1,
|
|
230
|
+
userInfo: [NSLocalizedDescriptionKey: "WebServer not initialized"]
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Swifter starts on all interfaces (0.0.0.0) by default
|
|
235
|
+
try server.start(defaultPort, forceIPv4: true)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// MARK: - Network Utilities
|
|
239
|
+
static func getWiFiAddress() -> String? {
|
|
240
|
+
var address: String?
|
|
241
|
+
var ifaddr: UnsafeMutablePointer<ifaddrs>?
|
|
242
|
+
|
|
243
|
+
guard getifaddrs(&ifaddr) == 0 else {
|
|
244
|
+
return nil
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
defer {
|
|
248
|
+
freeifaddrs(ifaddr)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
var ptr = ifaddr
|
|
252
|
+
while ptr != nil {
|
|
253
|
+
defer { ptr = ptr?.pointee.ifa_next }
|
|
254
|
+
|
|
255
|
+
guard let interface = ptr?.pointee else { continue }
|
|
256
|
+
|
|
257
|
+
let addrFamily = interface.ifa_addr.pointee.sa_family
|
|
258
|
+
|
|
259
|
+
// Check for IPv4 interface
|
|
260
|
+
guard addrFamily == UInt8(AF_INET) else { continue }
|
|
261
|
+
|
|
262
|
+
let name = String(cString: interface.ifa_name)
|
|
263
|
+
|
|
264
|
+
// WiFi interface (en0) or cellular (pdp_ip0)
|
|
265
|
+
guard name == "en0" || name == "pdp_ip0" else { continue }
|
|
266
|
+
|
|
267
|
+
var addr = interface.ifa_addr.pointee
|
|
268
|
+
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
|
|
269
|
+
|
|
270
|
+
let result = getnameinfo(
|
|
271
|
+
&addr,
|
|
272
|
+
socklen_t(interface.ifa_addr.pointee.sa_len),
|
|
273
|
+
&hostname,
|
|
274
|
+
socklen_t(hostname.count),
|
|
275
|
+
nil,
|
|
276
|
+
0,
|
|
277
|
+
NI_NUMERICHOST
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
guard result == 0 else { continue }
|
|
281
|
+
|
|
282
|
+
address = String(cString: hostname)
|
|
283
|
+
|
|
284
|
+
// Prefer en0 (WiFi) over pdp_ip0 (cellular)
|
|
285
|
+
if name == "en0" {
|
|
286
|
+
break
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return address
|
|
291
|
+
}
|
|
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
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Capacitor plugin for running a local HTTP server on the device.
|
|
6
|
+
* Allows receiving HTTP requests and sending responses from JavaScript.
|
|
7
|
+
*/
|
|
8
|
+
@objc(HttpLocalServerSwifterPlugin)
|
|
9
|
+
public class HttpLocalServerSwifterPlugin: CAPPlugin, CAPBridgedPlugin, HttpLocalServerSwifterDelegate {
|
|
10
|
+
|
|
11
|
+
public let identifier = "HttpLocalServerSwifterPlugin"
|
|
12
|
+
public let jsName = "HttpLocalServerSwifter"
|
|
13
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
14
|
+
CAPPluginMethod(name: "connect", returnType: CAPPluginReturnPromise),
|
|
15
|
+
CAPPluginMethod(name: "disconnect", returnType: CAPPluginReturnPromise),
|
|
16
|
+
CAPPluginMethod(name: "sendResponse", returnType: CAPPluginReturnPromise)
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
private var localServer: HttpLocalServerSwifter?
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Starts the local HTTP server.
|
|
23
|
+
* @return ip: The server's IP address
|
|
24
|
+
* @return port: The port the server is listening on
|
|
25
|
+
*/
|
|
26
|
+
@objc func connect(_ call: CAPPluginCall) {
|
|
27
|
+
if localServer == nil {
|
|
28
|
+
localServer = HttpLocalServerSwifter(delegate: self)
|
|
29
|
+
}
|
|
30
|
+
localServer?.connect(call)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Stops the local HTTP server.
|
|
35
|
+
* Cleans up all resources and pending requests.
|
|
36
|
+
*/
|
|
37
|
+
@objc func disconnect(_ call: CAPPluginCall) {
|
|
38
|
+
if localServer != nil {
|
|
39
|
+
localServer?.disconnect(call)
|
|
40
|
+
} else {
|
|
41
|
+
call.resolve()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Sends a response back to the client that made the request.
|
|
47
|
+
* @param requestId Unique request ID (received in 'onRequest')
|
|
48
|
+
* @param body Response body (typically stringified JSON)
|
|
49
|
+
*/
|
|
50
|
+
@objc func sendResponse(_ call: CAPPluginCall) {
|
|
51
|
+
guard let requestId = call.getString("requestId") else {
|
|
52
|
+
call.reject("Missing requestId")
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
guard let body = call.getString("body") else {
|
|
57
|
+
call.reject("Missing body")
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
HttpLocalServerSwifter.handleJsResponse(requestId: requestId, body: body)
|
|
62
|
+
call.resolve()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public func httpLocalServerSwifterDidReceiveRequest(_ data: [String: Any]) {
|
|
66
|
+
notifyListeners("onRequest", data: data)
|
|
67
|
+
}
|
|
68
|
+
}
|