about summary refs log tree commit diff stats
path: root/src/loader
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-09-28 17:54:13 +0200
committerbptato <nincsnevem662@gmail.com>2024-09-28 17:54:13 +0200
commit6a0e957e1f2c9f5bea0882efbf2e0494cd5074fa (patch)
tree3d6206a2bc8676d2fd913c3958e5186fc3375c2b /src/loader
parent9c257361388f5007871a36eea3abc815a8740d66 (diff)
downloadchawan-6a0e957e1f2c9f5bea0882efbf2e0494cd5074fa.tar.gz
loader: clean up connecterror
* allow string values for public errors
* remove unused errors
* update naming
Diffstat (limited to 'src/loader')
-rw-r--r--src/loader/connecterror.nim90
-rw-r--r--src/loader/loader.nim53
2 files changed, 87 insertions, 56 deletions
diff --git a/src/loader/connecterror.nim b/src/loader/connecterror.nim
index d8b06881..878bc8d0 100644
--- a/src/loader/connecterror.nim
+++ b/src/loader/connecterror.nim
@@ -1,36 +1,64 @@
-type ConnectErrorCode* = enum
-  ERROR_CGI_CACHED_BODY_NOT_FOUND = (-18, "cached request body not found")
-  ERROR_FAILED_TO_REDIRECT = (-17, "failed to redirect request body")
-  ERROR_URL_NOT_IN_CACHE = (-16, "URL was not found in the cache")
-  ERROR_FILE_NOT_IN_CACHE = (-15, "file was not found in the cache")
-  ERROR_FAILED_TO_EXECUTE_CGI_SCRIPT = (-14, "failed to execute CGI script")
-  ERROR_CGI_NO_DATA = (-13, "CGI script returned no data")
-  ERROR_CGI_MALFORMED_HEADER = (-12, "CGI script returned a malformed header")
-  ERROR_CGI_INVALID_CHA_CONTROL = (-11, "CGI got invalid Cha-Control header")
-  ERROR_TOO_MANY_REWRITES = (-10, "too many URI method map rewrites")
-  ERROR_INVALID_URI_METHOD_ENTRY = (-9, "invalid URI method entry")
-  ERROR_CGI_FILE_NOT_FOUND = (-8, "CGI file not found")
-  ERROR_INVALID_CGI_PATH = (-7, "invalid CGI path")
-  ERROR_FAIL_SETUP_CGI = (-6, "failed to set up CGI script")
-  ERROR_NO_CGI_DIR = (-5, "no local-CGI directory configured")
-  ERROR_SOURCE_NOT_FOUND = (-4, "clone source could not be found")
-  ERROR_LOADER_KILLED = (-3, "loader killed during transfer")
-  ERROR_DISALLOWED_URL = (-2, "url not allowed by filter")
-  ERROR_UNKNOWN_SCHEME = (-1, "unknown scheme")
-  CONNECTION_SUCCESS = (0, "connection successful")
-  ERROR_INTERNAL = (1, "internal error")
-  ERROR_INVALID_METHOD = (2, "invalid method")
-  ERROR_INVALID_URL = (3, "invalid URL")
-  ERROR_FILE_NOT_FOUND = (4, "file not found")
-  ERROR_CONNECTION_REFUSED = (5, "connection refused")
-  ERROR_PROXY_REFUSED_TO_CONNECT = (6, "proxy refused to connect")
-  ERROR_FAILED_TO_RESOLVE_HOST = (7, "failed to resolve host")
-  ERROR_FAILED_TO_RESOLVE_PROXY = (8, "failed to resolve proxy")
+type ConnectionError* = enum
+  ceCGIOutputHandleNotFound = -17
+  ceCGIFailedToOpenCacheOutput = -16
+  ceCGICachedBodyNotFound = -15
+  ceFailedToRedirect = -14
+  ceURLNotInCache = -13
+  ceFileNotInCache = -12
+  ceFailedToExecuteCGIScript = -11
+  ceCGIMalformedHeader = -10
+  ceCGIInvalidChaControl = -9
+  ceTooManyRewrites = -8
+  ceInvalidURIMethodEntry = -7
+  ceCGIFileNotFound = -6
+  ceInvalidCGIPath = -5
+  ceFailedToSetUpCGI = -4
+  ceNoCGIDir = -3
+  ceDisallowedURL = -2
+  ceUnknownScheme = -1
+  ceNone = 0
+  ceInternalError = (1, "InternalError")
+  ceInvalidMethod = (2, "InvalidMethod")
+  ceInvalidURL = (3, "InvalidURL")
+  ceFileNotFound = (4, "FileNotFound")
+  ceConnectionRefused = (5, "ConnectionRefused")
+  ceProxyRefusedToConnect = (6, "ProxyRefusedToConnect")
+  ceFailedToResolveHost = (7, "FailedToResolveHost")
+  ceFailedToResolveProxy = (8, "FailedToResolveProxy")
 
-converter toInt*(code: ConnectErrorCode): int =
+const ErrorMessages* = [
+  ceCGIOutputHandleNotFound: "request body output handle not found",
+  ceCGIFailedToOpenCacheOutput: "failed to open cache output",
+  ceCGICachedBodyNotFound: "cached request body not found",
+  ceFailedToRedirect: "failed to redirect request body",
+  ceURLNotInCache: "URL was not found in the cache",
+  ceFileNotInCache: "file was not found in the cache",
+  ceFailedToExecuteCGIScript: "failed to execute CGI script",
+  ceCGIMalformedHeader: "CGI script returned a malformed header",
+  ceCGIInvalidChaControl: "CGI got invalid Cha-Control header",
+  ceTooManyRewrites: "too many URI method map rewrites",
+  ceInvalidURIMethodEntry: "invalid URI method entry",
+  ceCGIFileNotFound: "CGI file not found",
+  ceInvalidCGIPath: "invalid CGI path",
+  ceFailedToSetUpCGI: "failed to set up CGI script",
+  ceNoCGIDir: "no local-CGI directory configured",
+  ceDisallowedURL: "url not allowed by filter",
+  ceUnknownScheme: "unknown scheme",
+  ceNone: "connection successful",
+  ceInternalError: "internal error",
+  ceInvalidMethod: "invalid method",
+  ceInvalidURL: "invalid URL",
+  ceFileNotFound: "file not found",
+  ceConnectionRefused: "connection refused",
+  ceProxyRefusedToConnect: "proxy refused to connect",
+  ceFailedToResolveHost: "failed to resolve host",
+  ceFailedToResolveProxy: "failed to resolve proxy",
+]
+
+converter toInt*(code: ConnectionError): int =
   return int(code)
 
 func getLoaderErrorMessage*(code: int): string =
-  if code in int(ConnectErrorCode.low)..int(ConnectErrorCode.high):
-    return $ConnectErrorCode(code)
+  if code in int(ConnectionError.low)..int(ConnectionError.high):
+    return ErrorMessages[ConnectionError(code)]
   return "unexpected error code " & $code
diff --git a/src/loader/loader.nim b/src/loader/loader.nim
index 732336f9..9ebc6917 100644
--- a/src/loader/loader.nim
+++ b/src/loader/loader.nim
@@ -100,7 +100,7 @@ func canRewriteForCGICompat(ctx: LoaderContext; path: string): bool =
       return true
   return false
 
-proc rejectHandle(handle: InputHandle; code: ConnectErrorCode; msg = "") =
+proc rejectHandle(handle: InputHandle; code: ConnectionError; msg = "") =
   handle.sendResult(code, msg)
   handle.close()
 
@@ -307,7 +307,7 @@ proc handleFirstLine(handle: InputHandle; line: string; headers: Headers;
   let k = line.until(':')
   if k.len == line.len:
     # invalid
-    handle.sendResult(ERROR_CGI_MALFORMED_HEADER)
+    handle.sendResult(ceCGIMalformedHeader)
     return crError
   let v = line.substr(k.len + 1).strip()
   if k.equalsIgnoreCase("Status"):
@@ -321,10 +321,13 @@ proc handleFirstLine(handle: InputHandle; line: string; headers: Headers;
     elif v.startsWithIgnoreCase("ConnectionError"):
       let errs = v.split(' ')
       if errs.len <= 1:
-        handle.sendResult(ERROR_CGI_INVALID_CHA_CONTROL)
+        handle.sendResult(ceCGIInvalidChaControl)
       else:
-        let fb = int32(ERROR_CGI_INVALID_CHA_CONTROL)
-        let code = int(parseInt32(errs[1]).get(fb))
+        var code = int32(ceCGIInvalidChaControl)
+        if (let x = parseInt32(errs[1]); x.isSome):
+          code = x.get
+        elif (let x = strictParseEnum[ConnectionError](errs[1]); x.isSome):
+          code = int32(x.get)
         var message = ""
         if errs.len > 2:
           message &= errs[2]
@@ -335,7 +338,7 @@ proc handleFirstLine(handle: InputHandle; line: string; headers: Headers;
       return crError
     elif v.startsWithIgnoreCase("ControlDone"):
       return crDone
-    handle.sendResult(ERROR_CGI_INVALID_CHA_CONTROL)
+    handle.sendResult(ceCGIInvalidChaControl)
     return crError
   handle.sendResult(0) # success
   headers.add(k, v)
@@ -584,20 +587,20 @@ proc parseCGIPath(ctx: LoaderContext; request: Request): CGIPath =
 proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
     request: Request; prevURL: URL; config: LoaderClientConfig) =
   if ctx.config.cgiDir.len == 0:
-    handle.sendResult(ERROR_NO_CGI_DIR)
+    handle.sendResult(ceNoCGIDir)
     return
   let cpath = ctx.parseCGIPath(request)
   if cpath.cmd == "" or cpath.basename in ["", ".", ".."] or
       cpath.basename[0] == '~':
-    handle.sendResult(ERROR_INVALID_CGI_PATH)
+    handle.sendResult(ceInvalidCGIPath)
     return
   if not fileExists(cpath.cmd):
-    handle.sendResult(ERROR_CGI_FILE_NOT_FOUND)
+    handle.sendResult(ceCGIFileNotFound)
     return
   # Pipe the response body as stdout.
   var pipefd: array[2, cint] # child -> parent
   if pipe(pipefd) == -1:
-    handle.sendResult(ERROR_FAIL_SETUP_CGI)
+    handle.sendResult(ceFailedToSetUpCGI)
     return
   let istreamOut = newPosixStream(pipefd[0]) # read by loader
   var ostreamOut = newPosixStream(pipefd[1]) # written by child
@@ -610,7 +613,7 @@ proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
     # RDWR, otherwise mmap won't work
     ostreamOut = newPosixStream(tmpf, O_CREAT or O_RDWR, 0o600)
     if ostreamOut == nil:
-      handle.sendResult(ERROR_FAIL_SETUP_CGI)
+      handle.sendResult(ceCGIFailedToOpenCacheOutput)
       return
     let cacheId = handle.output.outputId # welp
     client.cacheMap.add(CachedItem(
@@ -629,7 +632,7 @@ proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
     var n: int
     (istream, n) = client.openCachedItem(request.body.cacheId)
     if istream == nil:
-      handle.sendResult(ERROR_CGI_CACHED_BODY_NOT_FOUND)
+      handle.sendResult(ceCGICachedBodyNotFound)
       return
     cachedHandle = ctx.findCachedHandle(request.body.cacheId)
     if cachedHandle != nil: # cached item still open, switch to streaming mode
@@ -637,13 +640,13 @@ proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
   elif request.body.t == rbtOutput:
     outputIn = ctx.findOutput(request.body.outputId, client)
     if outputIn == nil:
-      handle.sendResult(ERROR_FAIL_SETUP_CGI)
+      handle.sendResult(ceCGIOutputHandleNotFound)
       return
   if request.body.t in {rbtString, rbtMultipart, rbtOutput} or
       request.body.t == rbtCache and istream2 != nil:
     var pipefdRead: array[2, cint] # parent -> child
     if pipe(pipefdRead) == -1:
-      handle.sendResult(ERROR_FAIL_SETUP_CGI)
+      handle.sendResult(ceFailedToSetUpCGI)
       return
     istream = newPosixStream(pipefdRead[0])
     ostream = newPosixStream(pipefdRead[1])
@@ -651,7 +654,7 @@ proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
   stderr.flushFile()
   let pid = fork()
   if pid == -1:
-    handle.sendResult(ERROR_FAIL_SETUP_CGI)
+    handle.sendResult(ceFailedToSetUpCGI)
   elif pid == 0:
     istreamOut.sclose() # close read
     discard dup2(ostreamOut.fd, 1) # dup stdout
@@ -679,7 +682,7 @@ proc loadCGI(ctx: LoaderContext; client: ClientData; handle: InputHandle;
       if ctx.handleMap[i] != nil:
         discard close(cint(i))
     discard execl(cstring(cpath.cmd), cstring(cpath.basename), nil)
-    let code = int(ERROR_FAILED_TO_EXECUTE_CGI_SCRIPT)
+    let code = int(ceFailedToExecuteCGIScript)
     stdout.write("Cha-Control: ConnectionError " & $code & " " &
       ($strerror(errno)).deleteChars({'\n', '\r'}))
     quit(1)
@@ -738,7 +741,7 @@ proc loadStream(ctx: LoaderContext; client: ClientData; handle: InputHandle;
       # not loading from cache, so cachedHandle is nil
       ctx.loadStreamRegular(handle, nil)
   do:
-    handle.sendResult(ERROR_FILE_NOT_FOUND, "stream not found")
+    handle.sendResult(ceFileNotFound, "stream not found")
 
 proc loadFromCache(ctx: LoaderContext; client: ClientData; handle: InputHandle;
     request: Request) =
@@ -750,7 +753,7 @@ proc loadFromCache(ctx: LoaderContext; client: ClientData; handle: InputHandle;
       ps.seek(startFrom)
     handle.stream = ps
     if ps == nil:
-      handle.rejectHandle(ERROR_FILE_NOT_IN_CACHE)
+      handle.rejectHandle(ceFileNotInCache)
       client.cacheMap.del(n)
       return
     handle.sendResult(0)
@@ -760,7 +763,7 @@ proc loadFromCache(ctx: LoaderContext; client: ClientData; handle: InputHandle;
     let cachedHandle = ctx.findCachedHandle(id)
     ctx.loadStreamRegular(handle, cachedHandle)
   else:
-    handle.sendResult(ERROR_URL_NOT_IN_CACHE)
+    handle.sendResult(ceURLNotInCache)
 
 # Data URL handler.
 # Moved back into loader from CGI, because data URLs can get extremely long
@@ -796,7 +799,7 @@ proc loadData(ctx: LoaderContext; handle: InputHandle; request: Request) =
   let url = request.url
   var ct = url.path.s.until(',')
   if AllChars - Ascii + Controls - {'\t', ' '} in ct:
-    handle.sendResult(ERROR_INVALID_URL, "invalid data URL")
+    handle.sendResult(ceInvalidURL, "invalid data URL")
     handle.close()
     return
   let sd = ct.len + 1 # data start
@@ -804,7 +807,7 @@ proc loadData(ctx: LoaderContext; handle: InputHandle; request: Request) =
   if ct.endsWith(";base64"):
     let d = atob0(body) # decode from ct end + 1
     if d.isNone:
-      handle.sendResult(ERROR_INVALID_URL, "invalid data URL")
+      handle.sendResult(ceInvalidURL, "invalid data URL")
       handle.close()
       return
     ct.setLen(ct.len - ";base64".len) # remove base64 indicator
@@ -853,11 +856,11 @@ proc loadResource(ctx: LoaderContext; client: ClientData;
         inc tries
         redo = true
       of ummrWrongURL:
-        handle.rejectHandle(ERROR_INVALID_URI_METHOD_ENTRY)
+        handle.rejectHandle(ceInvalidURIMethodEntry)
       of ummrNotFound:
-        handle.rejectHandle(ERROR_UNKNOWN_SCHEME)
+        handle.rejectHandle(ceUnknownScheme)
   if tries >= MaxRewrites:
-    handle.rejectHandle(ERROR_TOO_MANY_REWRITES)
+    handle.rejectHandle(ceTooManyRewrites)
 
 proc setupRequestDefaults(request: Request; config: LoaderClientConfig) =
   for k, v in config.defaultHeaders.table:
@@ -880,7 +883,7 @@ proc load(ctx: LoaderContext; stream: SocketStream; request: Request;
     handle.url = request.url
     handle.output.url = request.url
   if not config.filter.match(request.url):
-    handle.rejectHandle(ERROR_DISALLOWED_URL)
+    handle.rejectHandle(ceDisallowedURL)
   else:
     request.setupRequestDefaults(config)
     ctx.loadResource(client, config, request, handle)