]> cat aescling's git repositories - httpd-execline.git/commitdiff
Add optional support for gzip'd `Content-Encoding`
authorcat æscling <aescling@cat.family>
Tue, 30 Apr 2024 00:11:53 +0000 (20:11 -0400)
committercat æscling <aescling@cat.family>
Tue, 30 Apr 2024 01:18:48 +0000 (21:18 -0400)
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

README.md
visible-to-httpd/binaries/http-header-parse.execline
visible-to-httpd/binaries/httpd.execline

index 8abfb1695b303a6b119a91d164c533e6287e1d1e..f330ed00bf987ce4d5085d611bf6b5edfb82e55b 100644 (file)
--- 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&#x2019;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.
index 9d1a09c7a794b7297367fda1298942e1afb2bb19..8560e8eed7d97570de3891ecab44de8630eb75dc 100755 (executable)
@@ -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
index ace93e05288b32e34dbfab846fb5844442e412f4..27ec66fc214a47e4571dd9695ac371ed6ec2a7cd 100755 (executable)
@@ -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