expo-http-server 0.1.14-beta.5 → 0.1.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/README.md
CHANGED
|
@@ -96,6 +96,18 @@ export default function App() {
|
|
|
96
96
|
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
## Options
|
|
100
|
+
|
|
101
|
+
`setup` accepts an optional third argument:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
server.setup(9666, onStatusUpdate, { loopbackOnly: true });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
| Option | Default | Description |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `loopbackOnly` | `false` | Only accept connections from the device itself (`127.0.0.1`), so other devices on the network can't reach the server. |
|
|
110
|
+
|
|
99
111
|
## Running in the background
|
|
100
112
|
**iOS**: When the app is backgrounded the server will inevitably get paused. There is no getting around this. expo-http-server will start a [background task](https://developer.apple.com/documentation/uikit/uiapplication/1623031-beginbackgroundtask) that should provide a bit more background time, but this will only be ~25 seconds, which could be lowered by Apple in the future. expo-http-server will automatically pause the server when the time runs out, and resume it when the app is resumed.
|
|
101
113
|
|
|
@@ -64,6 +64,7 @@ class ExpoHttpServerModule : Module() {
|
|
|
64
64
|
private var configuredLoopbackOnly = false
|
|
65
65
|
private val routeConfigs = mutableListOf<RouteConfig>()
|
|
66
66
|
private val responses = ConcurrentHashMap<String, SimpleHttpResponse>()
|
|
67
|
+
private val pendingRequests = ConcurrentHashMap.newKeySet<String>()
|
|
67
68
|
private val onBindFailure: (String) -> Unit = { message ->
|
|
68
69
|
started = false
|
|
69
70
|
hasBoundSocket = false
|
|
@@ -78,6 +79,7 @@ class ExpoHttpServerModule : Module() {
|
|
|
78
79
|
val params: Map<String, String> = request.params()
|
|
79
80
|
val cookies: Map<String, String> = request.cookies().associate { it.name() to it.value() }
|
|
80
81
|
val requestId = UUID.randomUUID().toString()
|
|
82
|
+
pendingRequests.add(requestId)
|
|
81
83
|
sendEvent("onRequest", bundleOf(
|
|
82
84
|
"uuid" to uuid,
|
|
83
85
|
"requestId" to requestId,
|
|
@@ -92,6 +94,7 @@ class ExpoHttpServerModule : Module() {
|
|
|
92
94
|
while (!responses.containsKey(requestId) && System.currentTimeMillis() < deadline) {
|
|
93
95
|
Thread.sleep(10)
|
|
94
96
|
}
|
|
97
|
+
pendingRequests.remove(requestId)
|
|
95
98
|
val res = responses.remove(requestId) ?: return response
|
|
96
99
|
response.setBodyText(res.body)
|
|
97
100
|
response.setStatus(res.statusCode)
|
|
@@ -193,13 +196,15 @@ class ExpoHttpServerModule : Module() {
|
|
|
193
196
|
}
|
|
194
197
|
}
|
|
195
198
|
|
|
196
|
-
Function("respond") {
|
|
199
|
+
Function("respond") { requestId: String,
|
|
197
200
|
statusCode: Int,
|
|
198
201
|
statusDescription: String,
|
|
199
202
|
contentType: String,
|
|
200
203
|
headers: HashMap<String, String>,
|
|
201
204
|
body: String ->
|
|
202
|
-
|
|
205
|
+
if (pendingRequests.contains(requestId)) {
|
|
206
|
+
responses[requestId] = SimpleHttpResponse(statusCode, statusDescription, contentType, headers, body);
|
|
207
|
+
}
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
Function("stop") {
|
package/build/index.js
CHANGED
|
@@ -13,7 +13,7 @@ export const start = () => {
|
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
15
|
const response = await responseHandler.callback(event);
|
|
16
|
-
ExpoHttpServerModule.respond(event.requestId, response.statusCode || 200, response.statusDescription || "OK", response.contentType || "application/json", response.headers || {}, response.body
|
|
16
|
+
ExpoHttpServerModule.respond(event.requestId, response.statusCode || 200, response.statusDescription || "OK", response.contentType || "application/json", response.headers || {}, response.body ?? "{}");
|
|
17
17
|
}
|
|
18
18
|
catch {
|
|
19
19
|
ExpoHttpServerModule.respond(event.requestId, 500, "Internal Server Error", "application/json", {}, JSON.stringify({ error: "Handler failed" }));
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"expo-modules-core\";\n\nimport ExpoHttpServerModule from \"./ExpoHttpServerModule\";\n\nconst emitter = new EventEmitter(ExpoHttpServerModule);\nconst requestCallbacks: Callback[] = [];\nlet requestSubscription: ReturnType<typeof emitter.addListener> | null = null;\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"OPTIONS\";\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 requestId: 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 requestSubscription?.remove();\n requestSubscription = emitter.addListener<RequestEvent>(\"onRequest\", async (event) => {\n try {\n const responseHandler = requestCallbacks.find((c) => c.uuid === event.uuid);\n if (!responseHandler) {\n ExpoHttpServerModule.respond(\n event.requestId,\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.requestId,\n response.statusCode || 200,\n response.statusDescription || \"OK\",\n response.contentType || \"application/json\",\n response.headers || {},\n response.body
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"expo-modules-core\";\n\nimport ExpoHttpServerModule from \"./ExpoHttpServerModule\";\n\nconst emitter = new EventEmitter(ExpoHttpServerModule);\nconst requestCallbacks: Callback[] = [];\nlet requestSubscription: ReturnType<typeof emitter.addListener> | null = null;\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"OPTIONS\";\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 requestId: 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 requestSubscription?.remove();\n requestSubscription = emitter.addListener<RequestEvent>(\"onRequest\", async (event) => {\n try {\n const responseHandler = requestCallbacks.find((c) => c.uuid === event.uuid);\n if (!responseHandler) {\n ExpoHttpServerModule.respond(\n event.requestId,\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.requestId,\n response.statusCode || 200,\n response.statusDescription || \"OK\",\n response.contentType || \"application/json\",\n response.headers || {},\n response.body ?? \"{}\",\n );\n } catch {\n ExpoHttpServerModule.respond(\n event.requestId,\n 500,\n \"Internal Server Error\",\n \"application/json\",\n {},\n JSON.stringify({ error: \"Handler failed\" }),\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 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 interface SetupOptions {\n loopbackOnly?: boolean;\n}\n\nexport const setup = (\n port: number,\n onStatusUpdate?: (event: StatusEvent) => void,\n options: SetupOptions = {},\n) => {\n if (onStatusUpdate) {\n emitter.addListener<StatusEvent>(\"onStatusUpdate\", async (event) => {\n try {\n await onStatusUpdate(event);\n } catch {}\n });\n }\n ExpoHttpServerModule.setup(port, options.loopbackOnly ?? false);\n};\n\nexport const stop = () => {\n requestSubscription?.remove();\n requestSubscription = null;\n ExpoHttpServerModule.stop();\n};\n"]}
|
|
@@ -21,6 +21,10 @@ public class ExpoHttpServerModule: Module {
|
|
|
21
21
|
Function("route", routeHandler)
|
|
22
22
|
Function("respond", respondHandler)
|
|
23
23
|
Function("stop", stopHandler)
|
|
24
|
+
|
|
25
|
+
OnDestroy {
|
|
26
|
+
self.shutdown()
|
|
27
|
+
}
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
private func setupHandler(port: Int, loopbackOnly: Bool) {
|
|
@@ -38,14 +42,26 @@ public class ExpoHttpServerModule: Module {
|
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
stopped = false;
|
|
45
|
+
if (isListening) {
|
|
46
|
+
sendEvent("onStatusUpdate", [
|
|
47
|
+
"status": "STARTED",
|
|
48
|
+
"message": "Server started"
|
|
49
|
+
])
|
|
50
|
+
return
|
|
51
|
+
}
|
|
41
52
|
startServer(status: "STARTED", message: "Server started")
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
private func routeHandler(path: String, method: String, uuid: String) {
|
|
45
|
-
server.add(path, block: { (req, res, next) in
|
|
56
|
+
server.add(path, block: { [weak self] (req, res, next) in
|
|
46
57
|
DispatchQueue.main.async {
|
|
58
|
+
guard let self = self else {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
47
61
|
var bodyString = "{}"
|
|
48
|
-
if let body = req.body,
|
|
62
|
+
if let body = req.body,
|
|
63
|
+
JSONSerialization.isValidJSONObject(body),
|
|
64
|
+
let bodyData = try? JSONSerialization.data(withJSONObject: body) {
|
|
49
65
|
bodyString = String(data: bodyData, encoding: .utf8) ?? "{}"
|
|
50
66
|
}
|
|
51
67
|
let requestId = UUID().uuidString
|
|
@@ -60,6 +76,14 @@ public class ExpoHttpServerModule: Module {
|
|
|
60
76
|
"paramsJson": req.query.jsonString,
|
|
61
77
|
"cookiesJson": req.cookies?.jsonString ?? "{}"
|
|
62
78
|
])
|
|
79
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 30) { [weak self] in
|
|
80
|
+
self?.respondHandler(requestId: requestId,
|
|
81
|
+
statusCode: 504,
|
|
82
|
+
statusDescription: "Gateway Timeout",
|
|
83
|
+
contentType: "application/json",
|
|
84
|
+
headers: [:],
|
|
85
|
+
body: "{}")
|
|
86
|
+
}
|
|
63
87
|
}
|
|
64
88
|
}, recursive: false, method: CRHTTPMethod.fromString(method))
|
|
65
89
|
}
|
|
@@ -86,16 +110,19 @@ public class ExpoHttpServerModule: Module {
|
|
|
86
110
|
}
|
|
87
111
|
|
|
88
112
|
private func stopHandler() {
|
|
113
|
+
shutdown(status: "STOPPED", message: "Server stopped")
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private func shutdown(status: String? = nil, message: String? = nil) {
|
|
89
117
|
stopped = true;
|
|
90
118
|
if let observer = foregroundObserver {
|
|
91
119
|
NotificationCenter.default.removeObserver(observer)
|
|
92
120
|
foregroundObserver = nil
|
|
93
121
|
}
|
|
94
|
-
stopServer(status:
|
|
122
|
+
stopServer(status: status, message: message)
|
|
95
123
|
}
|
|
96
124
|
|
|
97
125
|
private func startServer(status: String, message: String) {
|
|
98
|
-
stopServer()
|
|
99
126
|
if let port = port {
|
|
100
127
|
var error: NSError?
|
|
101
128
|
server.startListening(&error, portNumber: UInt(port), interface: loopbackOnly ? "localhost" : nil)
|
|
@@ -134,8 +161,8 @@ public class ExpoHttpServerModule: Module {
|
|
|
134
161
|
|
|
135
162
|
private func beginBackgroundTask() {
|
|
136
163
|
if (bgTaskIdentifier == UIBackgroundTaskIdentifier.invalid) {
|
|
137
|
-
self.bgTaskIdentifier = UIApplication.shared.beginBackgroundTask(withName: "BgTask", expirationHandler: {
|
|
138
|
-
self
|
|
164
|
+
self.bgTaskIdentifier = UIApplication.shared.beginBackgroundTask(withName: "BgTask", expirationHandler: { [weak self] in
|
|
165
|
+
self?.stopServer(status: "PAUSED", message: "Server paused")
|
|
139
166
|
})
|
|
140
167
|
}
|
|
141
168
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED