expo-http-server 0.1.14-beta.0 → 0.1.14-beta.2

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.
@@ -18,10 +18,54 @@ class ExpoHttpServerModule : Module() {
18
18
  val headers: HashMap<String, String>,
19
19
  val body: String)
20
20
 
21
- private var server: Server? = null;
22
- private var started = false;
21
+ data class RouteConfig(val path: String, val method: String, val uuid: String)
22
+
23
+ private var server: Server? = null
24
+ private var started = false
25
+ private var configuredPort: Int = 0
26
+ private val routeConfigs = mutableListOf<RouteConfig>()
23
27
  private val responses = ConcurrentHashMap<String, SimpleHttpResponse>()
24
28
 
29
+ private fun handleRequest(uuid: String, request: Request, response: Response): Response {
30
+ val headers: Map<String, String> = request.headers()
31
+ val params: Map<String, String> = request.params()
32
+ val cookies: Map<String, String> = request.cookies().associate { it.name() to it.value() }
33
+ sendEvent("onRequest", bundleOf(
34
+ "uuid" to uuid,
35
+ "method" to request.method().name,
36
+ "path" to request.url(),
37
+ "body" to request.content(),
38
+ "headersJson" to JSONObject(headers).toString(),
39
+ "paramsJson" to JSONObject(params).toString(),
40
+ "cookiesJson" to JSONObject(cookies).toString(),
41
+ ))
42
+ val deadline = System.currentTimeMillis() + 30_000
43
+ while (!responses.containsKey(uuid) && System.currentTimeMillis() < deadline) {
44
+ Thread.sleep(10)
45
+ }
46
+ val res = responses.remove(uuid) ?: return response
47
+ response.setBodyText(res.body)
48
+ response.setStatus(res.statusCode)
49
+ response.addHeader("Content-Length", "" + res.body.length)
50
+ response.addHeader("Content-Type", res.contentType)
51
+ for ((key, value) in res.headers) {
52
+ response.addHeader(key, value)
53
+ }
54
+ return response
55
+ }
56
+
57
+ private fun buildServerWithRoutes(): Server {
58
+ var s: Server = AndroidServer.Builder {
59
+ port { configuredPort }
60
+ }.build()
61
+ for (route in routeConfigs) {
62
+ s = s.request(HttpMethod.getMethod(route.method), route.path) { request: Request, response: Response ->
63
+ handleRequest(route.uuid, request, response)
64
+ }
65
+ }
66
+ return s
67
+ }
68
+
25
69
  override fun definition() = ModuleDefinition {
26
70
 
27
71
  Name("ExpoHttpServer")
@@ -29,47 +73,24 @@ class ExpoHttpServerModule : Module() {
29
73
  Events("onStatusUpdate", "onRequest")
30
74
 
31
75
  Function("setup") { port: Int ->
76
+ configuredPort = port
32
77
  server?.close()
33
78
  started = false
34
- server = AndroidServer.Builder{
35
- port {
36
- port
37
- }
79
+ routeConfigs.clear()
80
+ server = AndroidServer.Builder {
81
+ port { configuredPort }
38
82
  }.build()
39
83
  }
40
84
 
41
85
  Function("route") { path: String, method: String, uuid: String ->
86
+ routeConfigs.add(RouteConfig(path, method, uuid))
42
87
  server = server?.request(HttpMethod.getMethod(method), path) { request: Request, response: Response ->
43
- val headers: Map<String, String> = request.headers()
44
- val params: Map<String, String> = request.params()
45
- val cookies: Map<String, String> = request.cookies().associate { it.name() to it.value() }
46
- sendEvent("onRequest", bundleOf(
47
- "uuid" to uuid,
48
- "method" to request.method().name,
49
- "path" to request.url(),
50
- "body" to request.content(),
51
- "headersJson" to JSONObject(headers).toString(),
52
- "paramsJson" to JSONObject(params).toString(),
53
- "cookiesJson" to JSONObject(cookies).toString(),
54
- ))
55
- val deadline = System.currentTimeMillis() + 30_000
56
- while (!responses.containsKey(uuid) && System.currentTimeMillis() < deadline) {
57
- Thread.sleep(10)
58
- }
59
- val res = responses.remove(uuid) ?: return@request response
60
- response.setBodyText(res.body)
61
- response.setStatus(res.statusCode)
62
- response.addHeader("Content-Length", "" + res.body.length)
63
- response.addHeader("Content-Type", res.contentType)
64
- for ((key, value) in res.headers) {
65
- response.addHeader(key, value)
66
- }
67
- return@request response
68
- };
88
+ handleRequest(uuid, request, response)
89
+ }
69
90
  }
70
91
 
71
92
  Function("start") {
72
- if (server == null) {
93
+ if (configuredPort == 0) {
73
94
  sendEvent("onStatusUpdate", bundleOf(
74
95
  "status" to "ERROR",
75
96
  "message" to "Server not setup / port not configured"
@@ -78,6 +99,11 @@ class ExpoHttpServerModule : Module() {
78
99
  if (!started) {
79
100
  try {
80
101
  started = true
102
+ // Always close and rebuild before starting so any existing socket binding
103
+ // is released, preventing BindException on the Netty event loop thread
104
+ // (which is asynchronous and not caught by this try/catch).
105
+ server?.close()
106
+ server = buildServerWithRoutes()
81
107
  server?.start()
82
108
  sendEvent("onStatusUpdate", bundleOf(
83
109
  "status" to "STARTED",
@@ -10,7 +10,7 @@ Pod::Spec.new do |s|
10
10
  s.license = package['license']
11
11
  s.author = package['author']
12
12
  s.homepage = package['homepage']
13
- s.platform = :ios, '13.4'
13
+ s.platform = :ios, '16.4'
14
14
  s.swift_version = '5.4'
15
15
  s.source = { git: 'https://github.com/simonsturge/expo-http-server' }
16
16
  s.static_framework = true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-http-server",
3
- "version": "0.1.14-beta.0",
3
+ "version": "0.1.14-beta.2",
4
4
  "description": "A simple HTTP server expo module (iOS/Android)",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",