about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/loader/cgi.nim8
-rw-r--r--src/loader/loader.nim19
-rw-r--r--src/loader/loaderhandle.nim6
-rw-r--r--src/loader/response.nim1
-rw-r--r--src/local/container.nim8
-rw-r--r--src/local/pager.nim4
-rw-r--r--src/server/buffer.nim6
7 files changed, 44 insertions, 8 deletions
diff --git a/src/loader/cgi.nim b/src/loader/cgi.nim
index 8fe96274..dfe66e22 100644
--- a/src/loader/cgi.nim
+++ b/src/loader/cgi.nim
@@ -87,7 +87,13 @@ proc handleFirstLine(handle: LoaderHandle, line: string, headers: Headers,
       else:
         let fb = int32(ERROR_CGI_INVALID_CHA_CONTROL)
         let code = int(parseInt32(errs[1]).get(fb))
-        discard handle.sendResult(code)
+        var message = ""
+        if errs.len > 2:
+          message &= errs[2]
+          for i in 3 ..< errs.len:
+            message &= ' '
+            message &= errs[i]
+        discard handle.sendResult(code, message)
       return RESULT_ERROR
     elif v.startsWithIgnoreCase("ControlDone"):
       return RESULT_CONTROL_DONE
diff --git a/src/loader/loader.nim b/src/loader/loader.nim
index acc7817a..8c39fe94 100644
--- a/src/loader/loader.nim
+++ b/src/loader/loader.nim
@@ -7,9 +7,17 @@
 # if success:
 #  S: status code
 #  S: headers
-#  S: response body
+#  if canredir:
+#    C: redir?
+#    if redir:
+#      C: redirection file handle (through sendFileHandle)
+#  S: response body (potentially into redirection file handle)
+# else:
+#  S: error message
 #
 # The body is passed to the stream as-is, so effectively nothing can follow it.
+# canredir is a mechanism for piping files into pager-opened processes
+# (i.e. mailcap).
 
 import std/nativesockets
 import std/net
@@ -453,6 +461,10 @@ proc onConnected*(loader: FileLoader, fd: int) =
     SocketStream(stream).source.getFd().setBlocking(false)
     promise.resolve(JSResult[Response].ok(response))
   else:
+    var msg: string
+    # msg is discarded.
+    #TODO maybe print if called from trusted code (i.e. global == client)?
+    stream.sread(msg)
     loader.unregisterFun(fd)
     loader.unregistered.add(fd)
     let err = newTypeError("NetworkError when attempting to fetch resource")
@@ -499,6 +511,11 @@ proc doRequest*(loader: FileLoader, request: Request, blocking = true,
     if loader.handleHeaders(request, response, stream):
       if not blocking:
         stream.source.getFd().setBlocking(blocking)
+  else:
+    var msg: string
+    stream.sread(msg)
+    if msg != "":
+      response.internalMessage = msg
   return response
 
 proc addref*(loader: FileLoader) =
diff --git a/src/loader/loaderhandle.nim b/src/loader/loaderhandle.nim
index dda00a1b..65638cdc 100644
--- a/src/loader/loaderhandle.nim
+++ b/src/loader/loaderhandle.nim
@@ -46,9 +46,13 @@ proc addOutputStream*(handle: LoaderHandle, stream: Stream) =
     let ms = newMultiStream(handle.ostream, stream)
     handle.ostream = ms
 
-proc sendResult*(handle: LoaderHandle, res: int): bool =
+proc sendResult*(handle: LoaderHandle, res: int, msg = ""): bool =
   try:
     handle.ostream.swrite(res)
+    if res == 0: # success
+      assert msg == ""
+    else: # error
+      handle.ostream.swrite(msg)
     return true
   except IOError: # broken pipe
     return false
diff --git a/src/loader/response.nim b/src/loader/response.nim
index 8f7d18b3..7aa07655 100644
--- a/src/loader/response.nim
+++ b/src/loader/response.nim
@@ -46,6 +46,7 @@ type
     unregisterFun*: proc()
     bodyRead*: Promise[string]
     charset*: Charset
+    internalMessage*: string # should NOT be exposed to JS!
 
 jsDestructor(Response)
 
diff --git a/src/local/container.nim b/src/local/container.nim
index a82f7aaf..c2edcf43 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -14,6 +14,7 @@ import io/serialize
 import js/dict
 import js/javascript
 import js/regex
+import loader/connecterror
 import loader/request
 import local/select
 import server/buffer
@@ -103,7 +104,8 @@ type
     lineshift: int
     numLines*: int
     replace*: Container
-    code*: int
+    code*: int # note: this is not the status code, but the ConnectErrorCode.
+    errorMessage*: string
     retry*: seq[URL]
     hlon*: bool # highlight on?
     sourcepair*: Container # pointer to buffer with a source view (may be nil)
@@ -1208,6 +1210,10 @@ proc load(container: Container) =
           container.source.contentType = some(res.contentType)
         container.triggerEvent(CHECK_MAILCAP)
       else:
+        if res.errorMessage != "":
+          container.errorMessage = res.errorMessage
+        else:
+          container.errorMessage = getLoaderErrorMessage(res.code)
         container.setLoadInfo("")
         container.triggerEvent(FAIL)
     else:
diff --git a/src/local/pager.nim b/src/local/pager.nim
index ab250986..1da7797d 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -26,7 +26,6 @@ import js/dict
 import js/javascript
 import js/regex
 import js/tojs
-import loader/connecterror
 import loader/loader
 import loader/request
 import local/container
@@ -1147,9 +1146,8 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo
       pager.gotoURL(newRequest(container.retry.pop()),
         ctype = container.contentType)
     else:
-      let errorMessage = getLoaderErrorMessage(container.code)
       pager.alert("Can't load " & $container.source.location & " (" &
-        errorMessage & ")")
+        container.errorMessage & ")")
     return false
   of SUCCESS:
     if container.replace != nil:
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index 2217522b..49624fb8 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -769,6 +769,7 @@ proc loadResources(buffer: Buffer): EmptyPromise =
 type ConnectResult* = object
   invalid*: bool
   code*: int
+  errorMessage*: string # if empty, use getLoaderErrorMessage
   needsAuth*: bool
   redirect*: Request
   contentType*: string
@@ -810,7 +811,10 @@ proc connect*(buffer: Buffer): ConnectResult {.proxy.} =
     let request = source.request
     let response = buffer.loader.doRequest(request, blocking = true, canredir = true)
     if response.body == nil:
-      return ConnectResult(code: response.res)
+      return ConnectResult(
+        code: response.res,
+        errorMessage: response.internalMessage
+      )
     if response.charset != CHARSET_UNKNOWN:
       charset = charset
     if buffer.source.contentType.isNone: