log.execline "fatal: ??"${1}"??: "${3}
}
-# (why does `hoc -e` not work?)
-backtick -i -n Content-Length {
- backtick -i -n message_length {
- pipeline { s6-echo -n -- ${2} }
- wc -c
- }
- importas -i -u message_length message_length
-
- pipeline { s6-echo -- ${message_length}"*2 + 288" }
- hoc
-}
-
backtick -i -n Date { date -u "+%a, %d %b %Y %T GMT" }
-
-backtick -i -n extra_headers { cat configuration/default_headers/default }
+backtick -i -n extra_headers { http-get-extra-headers.execline ${1} }
multisubstitute {
-# TODO: importas -i -u Content-Length Content-Length
importas -i -u Date Date
importas -i -u extra_headers extra_headers
- importas -D "invalid default hostname which should not match any hostname directory" hostname http_header_parse_Host
+ importas -D "?? no hostname ??" hostname http_header_parse_Host
}
if {
- s6-echo -n -- "HTTP/1.1 "${1}" "${2}"\r
-Content-Type: application/xhtml+xml; charset=utf-8\r
+ # if there is an error response page for this status code:
+ ifelse {
+ s6-test -d configuration/error_response_pages/${hostname}/${1}
+ -a -r configuration/error_response_pages/${hostname}/${1}
+ }
+ {
+ cd configuration/error_response_pages/${hostname}/${1}
+
+ backtick -D "application/xhtml+xml; charset=utf-8" -n Content-Type { cat Content-Type }
+ backtick -i -n Content-Length { wc -c message_body }
+
+ multisubstitute {
+ importas -i -u Content-Type Content-Type
+ importas -i -u Content-Length Content-Length
+ }
+
+ if {
+ s6-echo -n -- "HTTP/1.1 "${1}" "${2}"\r
+Content-Type: "${Content-Type}"\r
+Content-Length: "${Content-Length}"\r
Date: "${Date}"\r
"${extra_headers}"\r
\r
"
-}
-
-if {
- ifelse { s6-test -r configuration/error_response_pages/${hostname}/${1} }
- {
- # TODO: support `Content-Types`?? and `Content-Length`
- cat configuration/error_response_pages/${hostname}/${1}
+ }
+
+ cat message_body
}
+ # default: no error status page on file; use a hardcoded default
+
+ # (why does `hoc -e` not work?)
+ backtick -i -n Content-Length {
+ backtick -i -n message_length {
+ pipeline { s6-echo -n -- ${2} }
+ wc -c
+ }
+ importas -i -u message_length message_length
+
+ pipeline { s6-echo -- ${message_length}"*2 + 288" }
+ hoc
+ }
+ importas -i -u Content-Length Content-Length
+
+ if {
+ s6-echo -n -- "HTTP/1.1 "${1}" "${2}"\r
+Content-Type: application/xhtml+xml; charset=utf-8\r
+Content-Length: "${Content-Length}"\r
+Date: "${Date}"\r
+"${extra_headers}"\r
+\r
+"
+ }
s6-echo -n -- "<!DOCTYPE html>
<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">
<head>
</html>
"
}
+
# hack: write(3p) is unsafe
-#
s6-sleep -m 512
--- /dev/null
+#!/binaries/execlineb -WS0
+#
+# http-get-particular-headers.execline [status-code]
+#
+# sufficiently annoyingly complex resource-specific HTTP header logic that
+# gets reused a lot
+#
+# headers are specified in a header directory, which has a file for each
+# header you wish to send; this imposes structure with almost no parsing at all
+#
+# exploiting the filesystem as more or less a map (as opposed to the trivial
+# implementation: using a single file containing the desired headers) means the
+# user need not bother with editing files containing `\r\n`s
+# (however, it is almost certainly considerably more annoying to use)
+#
+# TODO: ? status code overrides support??
+# TODO: write a GUI?? with like, `yad(1)` or something??? idk
+
+multisubstitute {
+ importas -i hostname http_header_parse_Host
+ importas -i resource resource
+}
+
+foreground { log.execline "resource: "${resource} }
+
+backtick -n header-directory {
+ # for status code pages specifically
+ ifelse {
+ s6-test \${#} != 0
+ -a -d configuration/error_response_pages/${1}/headers
+ -a -r configuration/error_response_pages/${1}/headers
+ }
+ {
+ s6-echo -n -- configuration/error_response_pages/${1}/headers
+ }
+
+ # otherwise: prioritize header specifications in order of specificity:
+ # by resource, then by hostname, then the fallback (and finally nothing)
+ ifelse {
+ s6-test -d configuration/overrides/${resource}/headers
+ -a -r configuration/overrides/${resource}/headers
+ }
+ {
+ s6-echo -n -- configuration/overrides/${resource}/headers
+ }
+ ifelse {
+ s6-test -d configuration/default_headers/${hostname}
+ -a -r configuration/default_headers/${hostname}
+ }
+ {
+ s6-echo -n -- configuration/default_headers/${hostname}
+ }
+ # the preferred name for a DNS lookup should begin with an alphanumeric,
+ # so “-fallback”, since it begins with a hyphen, should never conflict
+ # with a hostname anybody would ever actually use
+ ifelse {
+ s6-test -d configuration/default_headers/-fallback
+ -a -r configuration/default_headers/-fallback
+ }
+ {
+ s6-echo -n -- configuration/default_headers/-fallback
+ }
+ exit 1
+}
+
+# (we output nothing if there is no applicable header directory, which is fine)
+if -t { s6-test -v header-directory }
+ importas -i -u header-directory header-directory
+
+ foreground { log.execline "header-directory: "${header-directory} }
+
+ cd ${header-directory}
+ elglob -0 -s header_names *
+
+ # we’ll strip out `\r`s and `\n`s from filenames and file contents, in
+ # case the configuration should ever be made in a mischevious way
+ forx header_name { ${header_names} }
+ importas -i -u header_name header_name
+ if {
+ pipeline { s6-echo -n -- ${header_name}": " }
+ tr -d "\r\n"
+ }
+ if {
+ pipeline { cat ${header_name} }
+ tr -d "\r\n"
+ }
+ # do make sure not to forget to supply the final newline
# Security Policy; for the latter, consider HTTP 301 redirects
#
# be warned!! we do not validate these overrides!
- backtick -i -n extra_headers {
- ifelse { s6-test -r configuration/default_headers/override/${resource} }
- {
- cat configuration/default_headers/override/${resource}
- }
- cat configuration/default_headers/default
- }
+ backtick -i -n extra_headers { http-get-extra-headers.execline }
backtick -D "200 ok" -n status_code_and_message {
if { s6-test -r configuration/overrides/${resource}/status_code }