about summary refs log tree commit diff stats
path: root/src/loader
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-12 22:53:49 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-12 23:04:47 +0100
commit64e6debefbc2ab00735b83ae1def168775006844 (patch)
tree0262e1b875c05ca453885bde0b24281047f87e4d /src/loader
parent2a8f0e7061babf03bc614554e3d5fd32220c305c (diff)
downloadchawan-64e6debefbc2ab00735b83ae1def168775006844.tar.gz
client: fix blocking reads on container connection
Sometimes, headers take a while to reach us even after the result has
been sent. e.g.

echo 'Cha-Control: Connected'
sleep 5
echo 'Cha-Control: ControlDone'

^ this froze the UI for 5 seconds, that's certainly not what we want.

Since we don't have a proper buffered reader yet, and I don't want to
write another disgusting hack like BufStream, we just use a state
machine to figure out how much we can read. Sounds bad, but in practice
it works just fine since loader's response patterns are very simple.
Diffstat (limited to 'src/loader')
-rw-r--r--src/loader/loader.nim42
-rw-r--r--src/loader/response.nim6
2 files changed, 19 insertions, 29 deletions
diff --git a/src/loader/loader.nim b/src/loader/loader.nim
index 904069a6..c4b497ac 100644
--- a/src/loader/loader.nim
+++ b/src/loader/loader.nim
@@ -785,12 +785,18 @@ proc connect(loader: FileLoader; buffered = true): SocketStream =
     return stream
   return nil
 
-#TODO: add init
-proc fetch*(loader: FileLoader; input: Request): FetchPromise =
+# Start a request. This should not block (not for a significant amount of time
+# anyway).
+proc startRequest*(loader: FileLoader; request: Request): SocketStream =
   let stream = loader.connect(buffered = false)
   stream.swrite(lcLoad)
-  stream.swrite(input)
+  stream.swrite(request)
   stream.flush()
+  return stream
+
+#TODO: add init
+proc fetch*(loader: FileLoader; input: Request): FetchPromise =
+  let stream = loader.startRequest(input)
   let fd = int(stream.fd)
   loader.registerFun(fd)
   let promise = FetchPromise()
@@ -866,8 +872,6 @@ proc handleHeaders(response: Response; request: Request; stream: SocketStream) =
   stream.sread(response.outputId)
   stream.sread(response.status)
   stream.sread(response.headers)
-  # Only a stream of the response body may arrive after this point.
-  response.body = stream
 
 proc onConnected*(loader: FileLoader, fd: int) =
   let connectData = loader.connecting[fd]
@@ -879,6 +883,8 @@ proc onConnected*(loader: FileLoader, fd: int) =
   let response = newResponse(res, request, stream)
   if res == 0:
     response.handleHeaders(request, stream)
+    # Only a stream of the response body may arrive after this point.
+    response.body = stream
     assert loader.unregisterFun != nil
     let realCloseImpl = stream.closeImpl
     stream.closeImpl = nil
@@ -938,31 +944,21 @@ proc onError*(loader: FileLoader; fd: int) =
     buffer[].buf = ""
     response.unregisterFun()
 
-# Start a request. This should not block (for a significant amount of time
-# anyway).
-proc startRequest*(loader: FileLoader; request: Request): SocketStream =
-  let stream = loader.connect(buffered = false)
-  stream.swrite(lcLoad)
-  stream.swrite(request)
-  stream.flush()
-  return stream
-
-# Read a response from a request stream (received from startRequest). This
-# blocks until headers are received.
-proc readResponse*(stream: SocketStream; request: Request): Response =
+# Note: this blocks until headers are received.
+proc doRequest*(loader: FileLoader; request: Request): Response =
+  let stream = loader.startRequest(request)
   let response = Response(url: request.url)
   stream.sread(response.res)
   if response.res == 0:
     response.handleHeaders(request, stream)
+    # Only a stream of the response body may arrive after this point.
+    response.body = stream
   else:
-    stream.sread(response.internalMessage)
+    var msg: string
+    stream.sread(msg)
+    stream.close()
   return response
 
-# Note: this blocks until headers are received; see above.
-proc doRequest*(loader: FileLoader; request: Request): Response =
-  let stream = loader.startRequest(request)
-  return stream.readResponse(request)
-
 proc shareCachedItem*(loader: FileLoader; id, targetPid: int) =
   let stream = loader.connect()
   if stream != nil:
diff --git a/src/loader/response.nim b/src/loader/response.nim
index f419c432..6b4ec64e 100644
--- a/src/loader/response.nim
+++ b/src/loader/response.nim
@@ -7,7 +7,6 @@ import io/promise
 import io/socketstream
 import js/error
 import js/javascript
-import loader/connecterror
 import loader/headers
 import loader/request
 import types/blob
@@ -154,10 +153,5 @@ proc json(ctx: JSContext, this: Response): Promise[JSResult[JSValue]]
     return ok(JS_ParseJSON(ctx, cstring(s), cast[csize_t](s.len),
       cstring"<input>")))
 
-func getErrorMessage*(this: Response): string =
-  if this.internalMessage != "":
-    return this.internalMessage
-  getLoaderErrorMessage(this.res)
-
 proc addResponseModule*(ctx: JSContext) =
   ctx.registerType(Response)