diff options
author | bptato <nincsnevem662@gmail.com> | 2024-09-28 17:54:13 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-09-28 17:54:13 +0200 |
commit | 6a0e957e1f2c9f5bea0882efbf2e0494cd5074fa (patch) | |
tree | 3d6206a2bc8676d2fd913c3958e5186fc3375c2b /src/loader | |
parent | 9c257361388f5007871a36eea3abc815a8740d66 (diff) | |
download | chawan-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.nim | 90 | ||||
-rw-r--r-- | src/loader/loader.nim | 53 |
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) |