From: cat æscling Date: Tue, 30 Apr 2024 00:11:53 +0000 (-0400) Subject: Add optional support for gzip'd `Content-Encoding` X-Git-Url: https://git.xn--scling-oua.cat.family/?a=commitdiff_plain;h=7249172d4d0686cab73585dd54bd3fd6a1c67a9a;p=httpd-execline.git Add optional support for gzip'd `Content-Encoding` If the client accepts gzip, and if the server is configured to use it, gzip(1p) the resource on tranfur. otherwise, just cat(1p) * Simplify regexp fur testing - Revert * Fix eltest syntax * Import `output_executable` * Correct Content-Encoding logic * Add log lines fur debugging - Revert * Look fur the correct header * Fix envvar name * Fix missing sequencing command on logging * Use input redirection fur output * Update README --- diff --git a/README.md b/README.md index 8abfb16..f330ed0 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,8 @@ feasible configuration is to place statically linked dependencies into + [toybox](http://www.landley.net/toybox/): `wc(1)`, `date(1p)`, `stat(1)`, `cat(1)`, `timeout(1)` - toybox’s `tr(1)` is pending but seems to work ++ [busybox](https://www.busybox.net/): `gzip(1)` (optional; required for gzip + encoding) + etc.: presumably, your system already has `chroot(1)` note that if you build execline and s6-portable-utils with slashpackage @@ -203,3 +205,9 @@ containing the text `301 moved permanently`; and + the file `./visible-to-httpd/configuration/overrides/httpd-execline.eerie.garden/index.xhtml/headers/Location` containing `https://github.com/single-right-quote/httpd.execline` + +### environment variables + ++ `httpd_execline_default_index`: the file to default to if a resource matches + a directory. defaults to `index.html` ++ `HTTPD_EXECLINE_GZIP`: if set, use `gzip(1)` to compress found resources. diff --git a/visible-to-httpd/binaries/http-header-parse.execline b/visible-to-httpd/binaries/http-header-parse.execline index 9d1a09c..8560e8e 100755 --- a/visible-to-httpd/binaries/http-header-parse.execline +++ b/visible-to-httpd/binaries/http-header-parse.execline @@ -94,6 +94,31 @@ case -N -- ${current_line_stripped} { tr A-Z a-z } + #### special case: content-encoding header + # + # test that the client accepts a gzip-encoded body, setting the + # variable HTTPD_EXECLINE_CLIENT_WANTS_GZIP if they do + ifelse { + eltest -v HTTPD_EXECLINE_GZIP + -a ${header_name} = accept-encoding + } + { + backtick -x HTTPD_EXECLINE_CLIENT_WANTS_GZIP { + backtick -E -i -n header_contents_lowercase { + pipeline { s6-echo -n -- ${header_contents} } + tr A-Z a-z + } + # TODO: is there a single regexp fur this? + eltest ${header_contents_lowercase} =~ "[, \t](x-)?gzip[, \t]" + -o ${header_contents_lowercase} =~ "[, \t](x-)?gzip$" + -o ${header_contents_lowercase} =~ "^(x-)?gzip[, \t]" + -o ${header_contents_lowercase} =~ "^(x-)?gzip$" + } + ${0} + ${supported_hostname_test} + ${@} + } + #### special case: host header # # short circuits the program diff --git a/visible-to-httpd/binaries/httpd.execline b/visible-to-httpd/binaries/httpd.execline index ace93e0..27ec66f 100755 --- a/visible-to-httpd/binaries/httpd.execline +++ b/visible-to-httpd/binaries/httpd.execline @@ -91,6 +91,29 @@ if -X -n -t { } #### 4. send response ### + backtick -i output_executable { + ifelse { + eltest -v HTTPD_EXECLINE_GZIP + -a -v HTTPD_EXECLINE_CLIENT_WANTS_GZIP + } + { + if { log.execline "info: client wants gzip" } + s6-echo -n -- gzip + } + s6-echo -n -- cat + } + + backtick -i -n Content-Encoding { + ifelse { + eltest -v HTTPD_EXECLINE_GZIP + -a -v HTTPD_EXECLINE_CLIENT_WANTS_GZIP + } + { + s6-echo -n -- gzip + } + s6-echo -n -- identity + } + ##### 4.1. determine found resource's Content-Type ### backtick -i -n Content-Type { define Content_Type_override_file configuration/overrides/${resource}/Content-Type @@ -167,7 +190,9 @@ if -X -n -t { ##### 4.3. send the response ### multisubstitute { + importas -i -u output_executable output_executable importas -i -u status_code_and_message status_code_and_message + importas -i -u Content-Encoding Content-Encoding importas -i -u Content-Length Content-Length importas -i -u Content-Type Content-Type importas -i -u Date Date @@ -176,6 +201,7 @@ if -X -n -t { } if { s6-echo -n -- "HTTP/1.1 "${status_code_and_message}"\r +Content-Encoding: "${Content-Encoding}"\r Content-Type: "${Content-Type}"\r Content-Length: "${Content-Length}"\r Last-Modified: "${Last-Modified}"\r @@ -185,7 +211,8 @@ Date: "${Date}${extra_headers}" } foreground { if -t { eltest \${method} = GET } - cat supported_domains/${resource} + redirfd -r 0 supported_domains/${resource} + ${output_executable} } # hack: write(3p) does not guarantee that all the # content actually gets written before this process