diff options
author | bptato <nincsnevem662@gmail.com> | 2024-08-03 01:14:41 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-08-03 01:54:35 +0200 |
commit | 4c64687290c908cd791a058dede9bd4f2a1c7757 (patch) | |
tree | 4e72720aa016320a02d19b4a051b9b9916b714f9 /src/loader | |
parent | 270cf870eb84e80f2de1f2be64b682849ca55585 (diff) | |
download | chawan-4c64687290c908cd791a058dede9bd4f2a1c7757.tar.gz |
loader: move back data URL handling
data URIs can get megabytes long; however, you can only stuff so many bytes into the envp. (This was thwarting my efforts to view pandoc- generated standalone HTML in Chawan.) So put `data:' back into the loader process.
Diffstat (limited to 'src/loader')
-rw-r--r-- | src/loader/loader.nim | 51 | ||||
-rw-r--r-- | src/loader/loaderhandle.nim | 4 |
2 files changed, 50 insertions, 5 deletions
diff --git a/src/loader/loader.nim b/src/loader/loader.nim index fec07d99..91212e24 100644 --- a/src/loader/loader.nim +++ b/src/loader/loader.nim @@ -407,6 +407,49 @@ proc loadFromCache(ctx: LoaderContext; client: ClientData; handle: LoaderHandle; else: handle.sendResult(ERROR_URL_NOT_IN_CACHE) +# Data URL handler. +# Moved back into loader from CGI, because data URLs can get extremely long +# and thus no longer fit into the environment. +proc loadDataSend(ctx: LoaderContext; handle: LoaderHandle; s, ct: string) = + handle.sendResult(0) + handle.sendStatus(200) + handle.sendHeaders(newHeaders({"Content-Type": ct})) + let buffer = newLoaderBuffer(size = s.len) + buffer.len = s.len + copyMem(buffer.page, unsafeAddr s[0], s.len) + let output = handle.output + case ctx.pushBuffer(output, buffer, 0) + of pbrUnregister: + if output.registered: + ctx.unregister(output) + output.oclose() + of pbrDone: + if output.registered or output.suspended: + output.istreamAtEnd = true + ctx.outputMap[output.ostream.fd] = output + else: + output.oclose() + +proc loadData(ctx: LoaderContext; handle: LoaderHandle; 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.close() + return + let sd = ct.len + 1 # data start + let body = percentDecode(url.path.s, sd) + 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.close() + return + ct.setLen(ct.len - ";base64".len) # remove base64 indicator + ctx.loadDataSend(handle, d.get, ct) + else: + ctx.loadDataSend(handle, body, ct) + proc loadResource(ctx: LoaderContext; client: ClientData; config: LoaderClientConfig; request: Request; handle: LoaderHandle) = var redo = true @@ -452,15 +495,17 @@ proc loadResource(ctx: LoaderContext; client: ClientData; ctx.loadFromCache(client, handle, request) assert handle.istream == nil handle.close() + elif request.url.scheme == "data": + ctx.loadData(handle, request) else: prevurl = request.url case ctx.config.uriMethodMap.findAndRewrite(request.url) - of URI_RESULT_SUCCESS: + of ummrSuccess: inc tries redo = true - of URI_RESULT_WRONG_URL: + of ummrWrongURL: handle.rejectHandle(ERROR_INVALID_URI_METHOD_ENTRY) - of URI_RESULT_NOT_FOUND: + of ummrNotFound: handle.rejectHandle(ERROR_UNKNOWN_SCHEME) if tries >= MaxRewrites: handle.rejectHandle(ERROR_TOO_MANY_REWRITES) diff --git a/src/loader/loaderhandle.nim b/src/loader/loaderhandle.nim index aa3a32d4..cb05efa1 100644 --- a/src/loader/loaderhandle.nim +++ b/src/loader/loaderhandle.nim @@ -93,9 +93,9 @@ func cap*(buffer: LoaderBuffer): int {.inline.} = template isEmpty*(output: OutputHandle): bool = output.currentBuffer == nil and not output.suspended -proc newLoaderBuffer*(): LoaderBuffer = +proc newLoaderBuffer*(size = LoaderBufferPageSize): LoaderBuffer = return LoaderBuffer( - page: cast[ptr UncheckedArray[uint8]](alloc(LoaderBufferPageSize)), + page: cast[ptr UncheckedArray[uint8]](alloc(size)), len: 0 ) |