expo-http-server 0.1.9 → 0.1.11

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/README.md CHANGED
@@ -49,19 +49,23 @@ export default function App() {
49
49
  }
50
50
  });
51
51
  server.route("/", "GET", async (request) => {
52
- console.log("Request", "/", "GET", JSON.stringify(request));
52
+ console.log("Request", "/", "GET", request);
53
53
  setLastCalled(Date.now());
54
54
  return {
55
55
  statusCode: 200,
56
+ headers: {
57
+ "Custom-Header": "Bazinga",
58
+ },
56
59
  contentType: "application/json",
57
60
  body: JSON.stringify(obj),
58
61
  };
59
62
  });
60
63
  server.route("/html", "GET", async (request) => {
61
- console.log("Request", "/html", "GET", JSON.stringify(request));
64
+ console.log("Request", "/html", "GET", request);
62
65
  setLastCalled(Date.now());
63
66
  return {
64
67
  statusCode: 200,
68
+ statusDescription: "OK - CUSTOM STATUS",
65
69
  contentType: "text/html",
66
70
  body: html,
67
71
  };
@@ -4,48 +4,23 @@ import androidx.core.os.bundleOf
4
4
  import expo.modules.kotlin.modules.Module
5
5
  import expo.modules.kotlin.modules.ModuleDefinition
6
6
  import com.safframework.server.core.AndroidServer
7
- import com.safframework.server.core.RequestHandler
8
7
  import com.safframework.server.core.Server
9
8
  import com.safframework.server.core.http.HttpMethod
10
9
  import com.safframework.server.core.http.Request
11
10
  import com.safframework.server.core.http.Response
12
11
  import org.json.JSONObject
13
- import java.util.UUID
14
12
 
15
13
  class ExpoHttpServerModule : Module() {
16
14
  class SimpleHttpResponse(val statusCode: Int,
15
+ val statusDescription: String,
17
16
  val contentType: String,
17
+ val headers: HashMap<String, String>,
18
18
  val body: String)
19
19
 
20
20
  private var server: Server? = null;
21
21
  private var started = false;
22
22
  private val responses = HashMap<String, SimpleHttpResponse>()
23
23
 
24
- private val requestHandler: RequestHandler = { request: Request, response: Response ->
25
- val uuid = UUID.randomUUID().toString()
26
- val headers: Map<String, String> = request.headers()
27
- val params: Map<String, String> = request.params()
28
- val cookies: Map<String, String> = request.cookies().associate { it.name() to it.value() }
29
- sendEvent("onRequest", bundleOf(
30
- "uuid" to uuid,
31
- "method" to request.method().name,
32
- "path" to request.url(),
33
- "body" to request.content(),
34
- "headersJson" to JSONObject(headers).toString(),
35
- "paramsJson" to JSONObject(params).toString(),
36
- "cookiesJson" to JSONObject(cookies).toString(),
37
- ))
38
- while (!responses.containsKey(uuid)) {
39
- Thread.sleep(10)
40
- }
41
- val res = responses[uuid]!!
42
- responses.remove(uuid);
43
- response.setBodyText(res.body)
44
- response.setStatus(res.statusCode)
45
- response.addHeader("Content-Length", "" + res.body.length)
46
- response.addHeader("Content-Type", res.contentType)
47
- }
48
-
49
24
  override fun definition() = ModuleDefinition {
50
25
 
51
26
  Name("ExpoHttpServer")
@@ -60,8 +35,34 @@ class ExpoHttpServerModule : Module() {
60
35
  }.build()
61
36
  }
62
37
 
63
- Function("route") { path: String, method: String ->
64
- server = server?.request(HttpMethod.getMethod(method), path, requestHandler);
38
+ Function("route") { path: String, method: String, uuid: String ->
39
+ server = server?.request(HttpMethod.getMethod(method), path) { request: Request, response: Response ->
40
+ val headers: Map<String, String> = request.headers()
41
+ val params: Map<String, String> = request.params()
42
+ val cookies: Map<String, String> = request.cookies().associate { it.name() to it.value() }
43
+ sendEvent("onRequest", bundleOf(
44
+ "uuid" to uuid,
45
+ "method" to request.method().name,
46
+ "path" to request.url(),
47
+ "body" to request.content(),
48
+ "headersJson" to JSONObject(headers).toString(),
49
+ "paramsJson" to JSONObject(params).toString(),
50
+ "cookiesJson" to JSONObject(cookies).toString(),
51
+ ))
52
+ while (!responses.containsKey(uuid)) {
53
+ Thread.sleep(10)
54
+ }
55
+ val res = responses[uuid]!!
56
+ response.setBodyText(res.body)
57
+ response.setStatus(res.statusCode)
58
+ response.addHeader("Content-Length", "" + res.body.length)
59
+ response.addHeader("Content-Type", res.contentType)
60
+ for ((key, value) in res.headers) {
61
+ response.addHeader(key, value)
62
+ }
63
+ responses.remove(uuid);
64
+ return@request response
65
+ };
65
66
  }
66
67
 
67
68
  Function("start") {
@@ -84,9 +85,11 @@ class ExpoHttpServerModule : Module() {
84
85
 
85
86
  Function("respond") { uuid: String,
86
87
  statusCode: Int,
88
+ statusDescription: String,
87
89
  contentType: String,
90
+ headers: HashMap<String, String>,
88
91
  body: String ->
89
- responses[uuid] = SimpleHttpResponse(statusCode, contentType, body);
92
+ responses[uuid] = SimpleHttpResponse(statusCode, statusDescription, contentType, headers, body);
90
93
  }
91
94
 
92
95
  Function("stop") {
package/build/index.d.ts CHANGED
@@ -18,12 +18,15 @@ export interface RequestEvent {
18
18
  }
19
19
  export interface Response {
20
20
  statusCode?: number;
21
+ statusDescription?: string;
21
22
  contentType?: string;
23
+ headers?: Record<string, string>;
22
24
  body?: string;
23
25
  }
24
26
  export interface Callback {
25
27
  method: string;
26
28
  path: string;
29
+ uuid: string;
27
30
  callback: (request: RequestEvent) => Promise<Response>;
28
31
  }
29
32
  export declare const start: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAC3D;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxD;AAED,eAAO,MAAM,KAAK,YAyBjB,CAAC;AAEF,eAAO,MAAM,KAAK,SACV,MAAM,UACJ,UAAU,sBACE,YAAY,KAAK,QAAQ,QAAQ,CAAC,SAQvD,CAAC;AAEF,eAAO,MAAM,KAAK,SACV,MAAM,4BACa,WAAW,KAAK,IAAI,sBAQ9C,CAAC;AAEF,eAAO,MAAM,IAAI,WAAoC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAC3D;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxD;AAED,eAAO,MAAM,KAAK,YAyBjB,CAAC;AAEF,eAAO,MAAM,KAAK,SACV,MAAM,UACJ,UAAU,sBACE,YAAY,KAAK,QAAQ,QAAQ,CAAC,SAUvD,CAAC;AAEF,eAAO,MAAM,KAAK,SACV,MAAM,4BACa,WAAW,KAAK,IAAI,sBAQ9C,CAAC;AAEF,eAAO,MAAM,IAAI,WAAoC,CAAC"}
package/build/index.js CHANGED
@@ -4,25 +4,25 @@ const emitter = new EventEmitter(ExpoHttpServerModule);
4
4
  const requestCallbacks = [];
5
5
  export const start = () => {
6
6
  emitter.addListener("onRequest", async (event) => {
7
- const callbacks = requestCallbacks.filter((c) => event.path.includes(c.path) && event.method === c.method);
8
- if (!callbacks.length) {
9
- ExpoHttpServerModule.respond(event.uuid, 200, "No callback", "No callback");
7
+ const responseHandler = requestCallbacks.find((c) => c.uuid === event.uuid);
8
+ if (!responseHandler) {
9
+ ExpoHttpServerModule.respond(event.uuid, 404, "Not Found", "application/json", {}, JSON.stringify({ error: "Handler not found" }));
10
10
  return;
11
11
  }
12
- for (const c of callbacks) {
13
- const response = await c.callback(event);
14
- ExpoHttpServerModule.respond(event.uuid, response.statusCode || 200, response.contentType || "application/json", response.body || "{}");
15
- }
12
+ const response = await responseHandler.callback(event);
13
+ ExpoHttpServerModule.respond(event.uuid, response.statusCode || 200, response.statusDescription || "OK", response.contentType || "application/json", response.headers || {}, response.body || "{}");
16
14
  });
17
15
  ExpoHttpServerModule.start();
18
16
  };
19
17
  export const route = (path, method, callback) => {
18
+ const uuid = Math.random().toString(16).slice(2);
20
19
  requestCallbacks.push({
21
20
  method,
22
21
  path,
22
+ uuid,
23
23
  callback,
24
24
  });
25
- ExpoHttpServerModule.route(path, method);
25
+ ExpoHttpServerModule.route(path, method, uuid);
26
26
  };
27
27
  export const setup = (port, onStatusUpdate) => {
28
28
  if (onStatusUpdate) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAE1D,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,oBAAoB,CAAC,CAAC;AACvD,MAAM,gBAAgB,GAAe,EAAE,CAAC;AAmCxC,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,EAAE;IACxB,OAAO,CAAC,WAAW,CAAe,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC7D,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAChE,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACtB,oBAAoB,CAAC,OAAO,CAC1B,KAAK,CAAC,IAAI,EACV,GAAG,EACH,aAAa,EACb,aAAa,CACd,CAAC;YACF,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACzC,oBAAoB,CAAC,OAAO,CAC1B,KAAK,CAAC,IAAI,EACV,QAAQ,CAAC,UAAU,IAAI,GAAG,EAC1B,QAAQ,CAAC,WAAW,IAAI,kBAAkB,EAC1C,QAAQ,CAAC,IAAI,IAAI,IAAI,CACtB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IACH,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,IAAY,EACZ,MAAkB,EAClB,QAAsD,EACtD,EAAE;IACF,gBAAgB,CAAC,IAAI,CAAC;QACpB,MAAM;QACN,IAAI;QACJ,QAAQ;KACT,CAAC,CAAC;IACH,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,IAAY,EACZ,cAA6C,EAC7C,EAAE;IACF,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,CAAC,WAAW,CAAc,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACjE,cAAc,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC","sourcesContent":["import { EventEmitter } from \"expo-modules-core\";\n\nimport ExpoHttpServerModule from \"./ExpoHttpServerModule\";\n\nconst emitter = new EventEmitter(ExpoHttpServerModule);\nconst requestCallbacks: Callback[] = [];\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n/**\n * PAUSED AND RESUMED are iOS only\n */\nexport type Status = \"STARTED\" | \"PAUSED\" | \"RESUMED\" | \"STOPPED\" | \"ERROR\";\n\nexport interface StatusEvent {\n status: Status;\n message: string;\n}\n\nexport interface RequestEvent {\n uuid: string;\n method: string;\n path: string;\n body: string;\n headersJson: string;\n paramsJson: string;\n cookiesJson: string;\n}\n\nexport interface Response {\n statusCode?: number;\n contentType?: string;\n body?: string;\n}\n\nexport interface Callback {\n method: string;\n path: string;\n callback: (request: RequestEvent) => Promise<Response>;\n}\n\nexport const start = () => {\n emitter.addListener<RequestEvent>(\"onRequest\", async (event) => {\n const callbacks = requestCallbacks.filter(\n (c) => event.path.includes(c.path) && event.method === c.method,\n );\n if (!callbacks.length) {\n ExpoHttpServerModule.respond(\n event.uuid,\n 200,\n \"No callback\",\n \"No callback\",\n );\n return;\n }\n for (const c of callbacks) {\n const response = await c.callback(event);\n ExpoHttpServerModule.respond(\n event.uuid,\n response.statusCode || 200,\n response.contentType || \"application/json\",\n response.body || \"{}\",\n );\n }\n });\n ExpoHttpServerModule.start();\n};\n\nexport const route = (\n path: string,\n method: HttpMethod,\n callback: (request: RequestEvent) => Promise<Response>,\n) => {\n requestCallbacks.push({\n method,\n path,\n callback,\n });\n ExpoHttpServerModule.route(path, method);\n};\n\nexport const setup = (\n port: number,\n onStatusUpdate?: (event: StatusEvent) => void,\n) => {\n if (onStatusUpdate) {\n emitter.addListener<StatusEvent>(\"onStatusUpdate\", async (event) => {\n onStatusUpdate(event);\n });\n }\n ExpoHttpServerModule.setup(port);\n};\n\nexport const stop = () => ExpoHttpServerModule.stop();\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAE1D,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,oBAAoB,CAAC,CAAC;AACvD,MAAM,gBAAgB,GAAe,EAAE,CAAC;AAsCxC,MAAM,CAAC,MAAM,KAAK,GAAG,GAAG,EAAE;IACxB,OAAO,CAAC,WAAW,CAAe,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC7D,MAAM,eAAe,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,oBAAoB,CAAC,OAAO,CAC1B,KAAK,CAAC,IAAI,EACV,GAAG,EACH,WAAW,EACX,kBAAkB,EAClB,EAAE,EACF,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAC/C,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvD,oBAAoB,CAAC,OAAO,CAC1B,KAAK,CAAC,IAAI,EACV,QAAQ,CAAC,UAAU,IAAI,GAAG,EAC1B,QAAQ,CAAC,iBAAiB,IAAI,IAAI,EAClC,QAAQ,CAAC,WAAW,IAAI,kBAAkB,EAC1C,QAAQ,CAAC,OAAO,IAAI,EAAE,EACtB,QAAQ,CAAC,IAAI,IAAI,IAAI,CACtB,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,IAAY,EACZ,MAAkB,EAClB,QAAsD,EACtD,EAAE;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjD,gBAAgB,CAAC,IAAI,CAAC;QACpB,MAAM;QACN,IAAI;QACJ,IAAI;QACJ,QAAQ;KACT,CAAC,CAAC;IACH,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,IAAY,EACZ,cAA6C,EAC7C,EAAE;IACF,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,CAAC,WAAW,CAAc,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACjE,cAAc,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC","sourcesContent":["import { EventEmitter } from \"expo-modules-core\";\n\nimport ExpoHttpServerModule from \"./ExpoHttpServerModule\";\n\nconst emitter = new EventEmitter(ExpoHttpServerModule);\nconst requestCallbacks: Callback[] = [];\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n/**\n * PAUSED AND RESUMED are iOS only\n */\nexport type Status = \"STARTED\" | \"PAUSED\" | \"RESUMED\" | \"STOPPED\" | \"ERROR\";\n\nexport interface StatusEvent {\n status: Status;\n message: string;\n}\n\nexport interface RequestEvent {\n uuid: string;\n method: string;\n path: string;\n body: string;\n headersJson: string;\n paramsJson: string;\n cookiesJson: string;\n}\n\nexport interface Response {\n statusCode?: number;\n statusDescription?: string;\n contentType?: string;\n headers?: Record<string, string>;\n body?: string;\n}\n\nexport interface Callback {\n method: string;\n path: string;\n uuid: string;\n callback: (request: RequestEvent) => Promise<Response>;\n}\n\nexport const start = () => {\n emitter.addListener<RequestEvent>(\"onRequest\", async (event) => {\n const responseHandler = requestCallbacks.find((c) => c.uuid === event.uuid);\n if (!responseHandler) {\n ExpoHttpServerModule.respond(\n event.uuid,\n 404,\n \"Not Found\",\n \"application/json\",\n {},\n JSON.stringify({ error: \"Handler not found\" }),\n );\n return;\n }\n const response = await responseHandler.callback(event);\n ExpoHttpServerModule.respond(\n event.uuid,\n response.statusCode || 200,\n response.statusDescription || \"OK\",\n response.contentType || \"application/json\",\n response.headers || {},\n response.body || \"{}\",\n );\n });\n ExpoHttpServerModule.start();\n};\n\nexport const route = (\n path: string,\n method: HttpMethod,\n callback: (request: RequestEvent) => Promise<Response>,\n) => {\n const uuid = Math.random().toString(16).slice(2);\n requestCallbacks.push({\n method,\n path,\n uuid,\n callback,\n });\n ExpoHttpServerModule.route(path, method, uuid);\n};\n\nexport const setup = (\n port: number,\n onStatusUpdate?: (event: StatusEvent) => void,\n) => {\n if (onStatusUpdate) {\n emitter.addListener<StatusEvent>(\"onStatusUpdate\", async (event) => {\n onStatusUpdate(event);\n });\n }\n ExpoHttpServerModule.setup(port);\n};\n\nexport const stop = () => ExpoHttpServerModule.stop();\n"]}
@@ -34,10 +34,9 @@ public class ExpoHttpServerModule: Module {
34
34
  startServer(status: "STARTED", message: "Server started")
35
35
  }
36
36
 
37
- private func routeHandler(path: String, method: String) {
37
+ private func routeHandler(path: String, method: String, uuid: String) {
38
38
  server.add(path, block: { (req, res, next) in
39
39
  DispatchQueue.main.async {
40
- let uuid = UUID().uuidString
41
40
  var bodyString = "{}"
42
41
  if let body = req.body, let bodyData = try? JSONSerialization.data(withJSONObject: body) {
43
42
  bodyString = String(data: bodyData, encoding: .utf8) ?? "{}"
@@ -53,18 +52,23 @@ public class ExpoHttpServerModule: Module {
53
52
  "cookiesJson": req.cookies?.jsonString ?? "{}"
54
53
  ])
55
54
  }
56
- }, recursive: true, method: CRHTTPMethod.fromString(method))
55
+ }, recursive: false, method: CRHTTPMethod.fromString(method))
57
56
  }
58
57
 
59
58
  private func respondHandler(udid: String,
60
59
  statusCode: Int,
60
+ statusDescription: String,
61
61
  contentType: String,
62
+ headers: [String: String],
62
63
  body: String) {
63
64
  DispatchQueue.main.async {
64
65
  if let response = self.responses[udid] {
65
- response.setStatusCode(UInt(statusCode), description: "ExpoHttpServer")
66
+ response.setStatusCode(UInt(statusCode), description: statusDescription)
66
67
  response.setValue(contentType, forHTTPHeaderField: "Content-type")
67
68
  response.setValue("\(body.count)", forHTTPHeaderField: "Content-Length")
69
+ for (key, value) in headers {
70
+ response.setValue(value, forHTTPHeaderField: key)
71
+ }
68
72
  response.send(body);
69
73
  self.responses[udid] = nil;
70
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-http-server",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "A simple HTTP server expo module (iOS/Android)",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
package/src/index.ts CHANGED
@@ -28,39 +28,42 @@ export interface RequestEvent {
28
28
 
29
29
  export interface Response {
30
30
  statusCode?: number;
31
+ statusDescription?: string;
31
32
  contentType?: string;
33
+ headers?: Record<string, string>;
32
34
  body?: string;
33
35
  }
34
36
 
35
37
  export interface Callback {
36
38
  method: string;
37
39
  path: string;
40
+ uuid: string;
38
41
  callback: (request: RequestEvent) => Promise<Response>;
39
42
  }
40
43
 
41
44
  export const start = () => {
42
45
  emitter.addListener<RequestEvent>("onRequest", async (event) => {
43
- const callbacks = requestCallbacks.filter(
44
- (c) => event.path.includes(c.path) && event.method === c.method,
45
- );
46
- if (!callbacks.length) {
46
+ const responseHandler = requestCallbacks.find((c) => c.uuid === event.uuid);
47
+ if (!responseHandler) {
47
48
  ExpoHttpServerModule.respond(
48
49
  event.uuid,
49
- 200,
50
- "No callback",
51
- "No callback",
50
+ 404,
51
+ "Not Found",
52
+ "application/json",
53
+ {},
54
+ JSON.stringify({ error: "Handler not found" }),
52
55
  );
53
56
  return;
54
57
  }
55
- for (const c of callbacks) {
56
- const response = await c.callback(event);
57
- ExpoHttpServerModule.respond(
58
- event.uuid,
59
- response.statusCode || 200,
60
- response.contentType || "application/json",
61
- response.body || "{}",
62
- );
63
- }
58
+ const response = await responseHandler.callback(event);
59
+ ExpoHttpServerModule.respond(
60
+ event.uuid,
61
+ response.statusCode || 200,
62
+ response.statusDescription || "OK",
63
+ response.contentType || "application/json",
64
+ response.headers || {},
65
+ response.body || "{}",
66
+ );
64
67
  });
65
68
  ExpoHttpServerModule.start();
66
69
  };
@@ -70,12 +73,14 @@ export const route = (
70
73
  method: HttpMethod,
71
74
  callback: (request: RequestEvent) => Promise<Response>,
72
75
  ) => {
76
+ const uuid = Math.random().toString(16).slice(2);
73
77
  requestCallbacks.push({
74
78
  method,
75
79
  path,
80
+ uuid,
76
81
  callback,
77
82
  });
78
- ExpoHttpServerModule.route(path, method);
83
+ ExpoHttpServerModule.route(path, method, uuid);
79
84
  };
80
85
 
81
86
  export const setup = (