diff --git a/src/constants.sh b/src/constants.sh
index 6d74044..99f7a86 100644
--- a/src/constants.sh
+++ b/src/constants.sh
@@ -1,5 +1,8 @@
# shellcheck disable=SC2034 # for now
+[ -n "${HTTP_GUARD__CONSTANTS_SH+x}" ] && return
+export HTTP_GUARD__CONSTANTS_SH=''
+
readonly HTTP_SERVER_VERSION='0.1.0'
readonly HTTP_PROTOCOL_VERSION='HTTP/1.1'
readonly HTTP_SERVER_STRING="httb/${HTTP_SERVER_VERSION}"
@@ -69,6 +72,7 @@ declare -Ar HTTP_SUPPORTED_METHODS=(
http::_status_code_page() {
cat <<-EOF
+
${1} ${HTTP_METHOD_NAMES["$1"]}
@@ -78,5 +82,5 @@ http::_status_code_page() {
Server: ${HTTP_SERVER_STRING}
-EOF
+ EOF
}
diff --git a/src/helpers.sh b/src/helpers.sh
index fe1d4f7..3b9051c 100644
--- a/src/helpers.sh
+++ b/src/helpers.sh
@@ -1,8 +1,11 @@
#!/bin/bash
-# shellcheck disable=SC2015
+
+[ -n "${HTTP_GUARD__HELPERS_SH+x}" ] && return
+export HTTP_GUARD__HELPERS_SH=''
http::_tempfile() {
[ ! -d "/dev/shm" ] && TMP_FOLDER="/tmp" || TMP_FOLDER="/dev/shm"
- [ ! -d "${TMP_FOLDER}/httb-server" ] && mkdir "${TMP_FOLDER}/httb-server" ||
+ # shellcheck disable=SC2015
+ [ ! -d "${TMP_FOLDER}/httb-server" ] && mkdir "${TMP_FOLDER}/httb-server" ||
mktemp -t 'httb-server.XXXXXXXXXXXX' -p "${TMP_FOLDER}/httb-server"
}
diff --git a/src/http_server.sh b/src/http_server.sh
index e0b9f5a..2518127 100644
--- a/src/http_server.sh
+++ b/src/http_server.sh
@@ -1,22 +1,42 @@
#!/bin/bash
-# shellcheck shell=bash
set -e
shopt -s globstar extglob dotglob
-# shellcheck source-path=../
-HTTP_SCRIPT_PATH="$(dirname "$(readlink -e "${BASH_SOURCE[0]:-$0}")")"
+[ -n "${HTTP_GUARD__HTTP_SERVER_SH+x}" ] && return
+export HTTP_GUARD__HTTP_SERVER_SH=''
+
+: "${HTTP_SCRIPT_PATH:="$(dirname "$(readlink -e "${BASH_SOURCE[0]:-$0}")")"}"
readonly HTTP_SCRIPT_PATH
+# shellcheck source=./constants.sh
. "${HTTP_SCRIPT_PATH}/constants.sh"
+# shellcheck source=./helpers.sh
. "${HTTP_SCRIPT_PATH}/helpers.sh"
-
+# shellcheck source=./request.sh
+. "${HTTP_SCRIPT_PATH}/request.sh"
+# shellcheck source=./response.sh
+. "${HTTP_SCRIPT_PATH}/response.sh"
+# shellcheck source=./markdown.sh
+. "${HTTP_SCRIPT_PATH}/markdown.sh"
declare -A http__handlers=()
declare -A http__all_routes=()
# -- CONFIGURATION --
+http::run() {
+ if [[ "$1" = "run" ]]; then
+ echo "Listening on ${HTTP_HOST:=${HTTP_DEFAULT_HOST}}:${HTTP_PORT:=${HTTP_DEFAULT_PORT}}"
+ socat "TCP-LISTEN:${HTTP_PORT},bind=${HTTP_HOST},fork,reuseport" "EXEC:$(readlink -e "$0") parse"
+ elif [[ "$1" = "parse" ]]; then
+ http::_process_request
+ else
+ http::_cmd_help >&2
+ exit 1
+ fi
+}
+
http::host() { export HTTP_HOST_NAME="$1"; }
http::bind() { export HTTP_HOST="${1:-${HTTP_DEFAULT_HOST}}"; export HTTP_PORT="${2:-${HTTP_DEFAULT_PORT}}"; }
http::markdown_base() { export HTTP_MARKDOWN_BASE="$1"; }
@@ -27,90 +47,20 @@ http::static_folder() {
export HTTP_STATIC_FOLDER="$2";
}
-# -- PUBLIC METHODS --
http::route() {
local _method
while read -r _method; do
# temp until all methods are suppoorted
[[ -z "${HTTP_SUPPORTED_METHODS["${_method}"]}" ]] && echo "$1: Method ${_method} not implemented!" >&2 && exit 1
- http__handlers["$_method,$3"]="$1"
+ http__handlers["$_method,$3"]="$1" # bad, skill issue
http__all_routes["$3"]=1
done <<< "${2/ /$'\n'}"
}
+
http::get() { http::route "$1" "GET" "$2"; }
-# -- REQUEST PROCESSING --
-
-http::_parse_headers() {
- read -r request_method request_path request_version
-
- while read -r header_; do
- [[ -z "${header_/$'\r'/}" ]] && break
- local h_name h_value
- IFS=: read -r h_name h_value <<< "${header_/': '/:}"
- request_headers["${h_name}"]="${h_value}"
- done
-}
-
-http::_parse_body() { :; } # TODO
-
-http::_route_request() {
- [[ -z "${HTTP_SUPPORTED_METHODS[${request_method}]}" ]] && http::response 501 && return 1
- local glob_endpoint handler path_found
-
- for glob_endpoint in "${!http__all_routes[@]}"; do # FIXME
- # shellcheck disable=SC2053
- if [[ "${request_path}" == ${glob_endpoint} ]]; then
- declare -rx HTTP_REQUEST_GLOB="${glob_endpoint}"
- path_found=1
- break
- fi
- done
-
- handler="${http__handlers["$request_method,$glob_endpoint"]}"
-
- if [[ -z "${path_found}" ]]; then
- http::response 404; return 1
- elif [[ -z "${handler}" ]]; then
- http::response 405; return 1
- else
- "${handler}"
- fi
-}
-
-# -- RESPONSE PROCESSING --
-
-http::_response_base_headers() {
- connection_string="${HTTP_PROTOCOL_VERSION} $1 ${HTTP_METHOD_NAMES["$1"]}"
- response_headers["Server"]="${HTTP_SERVER_STRING}"
- response_headers["Connection"]="close"
- response_headers["Date"]="$(date -Ru)"
- response_headers["Cache-control"]="no-cache"
- response_headers["Cache-control"]="max-age=0"
-}
-
-http::_set_response_content_type() {
- response_headers["Content-Type"]="$(file -ib "$1")"
-}
-
-# $1 = file with content $2 = filename
-http::_response_content_headers() {
- response_headers["Content-Length"]="$(wc -c "$1" | cut -d ' ' -f 1)"
- [[ -z "${response_headers["Content-Type"]}" ]] && response_headers["Content-Type"]="$(file -ib "$1")"
- echo
-}
-
-http::_response_content() {
- local -r content_file="$(http::_tempfile)" # TODO mb adapt to mkfifo pipes
- cat - > "${content_file}"
-
- http::_response_content_headers "${content_file}"
-
- cat "${content_file}"
- rm -f "${content_file}"
-}
http::_static_file() {
local uri_path="${request_path#"${HTTP_REQUEST_GLOB%'**'}"}"
@@ -119,33 +69,12 @@ http::_static_file() {
http::file "${filename}"
}
-http::response() {
- local status_code page
- [[ -n "${HTTP_METHOD_NAMES["$1"]}" ]] && status_code="$1" || status_code="500"
- page="$(http::_status_code_page "${status_code}")"
- response_headers["Content-Type"]="text/html"
- http::_response_base_headers "${status_code}"
- http::_response_content <<< "${page}"
-}
-
-http::file() {
- [[ ! -f "$1" ]] && http::response 500 && return 1
- http::_response_base_headers "200"
- http::_set_response_content_type "$1"
- http::_response_content < "$1"
-}
-
-http::html() { response_headers["Content-Type"]="text/html" http::file "$@"; }
-
-http::format_markdown() { :; } # TODO
-
-# -- COMMAND LINE LOGIC --
http::_process_request() {
- declare -Ax request_headers response_headers
- export request_method request_path request_version connection_string
+ local -A request_headers response_headers
+ local request_method request_path request_version connection_string
- http::_parse_headers || { http::response 500 && return 0; }
+ http::_parse_headers || { http::response 405 && return 0; }
# { [[ "${request_method}" != "GET" ]] && http::_parse_body; || { http::response 500 && return 0; }
if [[ -n "${HTTP_HOST_NAME}" && "${HTTP_HOST_NAME}" != "${request_headers["Host"]%:*}" ]]; then
@@ -153,8 +82,10 @@ http::_process_request() {
return 0
fi
+ : "${request_version}"
+
http::_route_request
- [[ -z "${connection_string}" ]] && http::response 500 && return 0
+ [[ -z "${connection_string}" ]] && { http::response 500; return 0; }
return 0
}
@@ -168,14 +99,3 @@ http::_cmd_help() {
echo " parse Parse http request from stdin and output to stdout"
}
-http::run() {
- if [[ "$1" = "run" ]]; then
- echo "Listening on ${HTTP_HOST:=${HTTP_DEFAULT_HOST}}:${HTTP_PORT:=${HTTP_DEFAULT_PORT}}"
- socat "TCP-LISTEN:${HTTP_PORT},bind=${HTTP_HOST},fork,reuseport" "EXEC:$(readlink -e "$0") parse"
- elif [[ "$1" = "parse" ]]; then
- http::_process_request
- else
- http::_cmd_help >&2
- exit 1
- fi
-}
diff --git a/src/markdown.sh b/src/markdown.sh
new file mode 100644
index 0000000..fc2eec0
--- /dev/null
+++ b/src/markdown.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+[ -n "${HTTP_GUARD__MARKDOWN_SH+x}" ] && return
+export HTTP_GUARD__MARKDOWN_SH=''
+
+
+http::_convert_to_md() {
+ local -a pandoc_options=(
+ '--from=gfm+tex_math_dollars '
+ '--to=html'
+ '--mathjax'
+ '--toc'
+ "--template=${HTTP_MARKDOWN_BASE:-'default.html5'}"
+ )
+ pandoc "${pandoc_options[@]}" "$1"
+}
+
+http::md() {
+ [[ ! -f "$1" ]] && { http::response 500 && return 1; }
+ markdown="$(http::_convert_to_md "$1")"
+ http::_response_base_headers "200"
+ response_headers["Content-Type"]="text/html"
+ http::_response_content_headers <(printf "%s" "$markdown")
+ http::_output_response_headers
+ printf "%s" "$markdown"
+}
diff --git a/src/mime.types b/src/mime.types
new file mode 100644
index 0000000..2c61f57
--- /dev/null
+++ b/src/mime.types
@@ -0,0 +1,985 @@
+application/andrew-inset ez
+application/applixware aw
+application/atom+xml atom
+application/atomcat+xml atomcat
+application/atomsvc+xml atomsvc
+application/ccxml+xml ccxml
+application/cdmi-capability cdmia
+application/cdmi-container cdmic
+application/cdmi-domain cdmid
+application/cdmi-object cdmio
+application/cdmi-queue cdmiq
+application/cu-seeme cu
+application/davmount+xml davmount
+application/docbook+xml dbk
+application/dssc+der dssc
+application/dssc+xml xdssc
+application/ecmascript ecma
+application/emma+xml emma
+application/epub+zip epub
+application/exi exi
+application/font-tdpfr pfr
+application/gml+xml gml
+application/gpx+xml gpx
+application/gxf gxf
+application/hyperstudio stk
+application/inkml+xml ink
+application/inkml+xml inkml
+application/ipfix ipfix
+application/java-archive jar
+application/java-serialized-object ser
+application/java-vm class
+application/javascript js
+application/json json
+application/jsonml+json jsonml
+application/lost+xml lostxml
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/mads+xml mads
+application/marc mrc
+application/marcxml+xml mrcx
+application/mathematica ma
+application/mathematica nb
+application/mathematica mb
+application/mathml+xml mathml
+application/mbox mbox
+application/mediaservercontrol+xml mscml
+application/metalink+xml metalink
+application/metalink4+xml meta4
+application/mets+xml mets
+application/mods+xml mods
+application/mp21 m21
+application/mp21 mp21
+application/mp4 mp4s
+application/msword doc
+application/msword dot
+application/mxf mxf
+application/octet-stream bin
+application/octet-stream dms
+application/octet-stream lrf
+application/octet-stream mar
+application/octet-stream so
+application/octet-stream dist
+application/octet-stream distz
+application/octet-stream pkg
+application/octet-stream bpk
+application/octet-stream dump
+application/octet-stream elc
+application/octet-stream deploy
+application/oda oda
+application/oebps-package+xml opf
+application/ogg ogx
+application/omdoc+xml omdoc
+application/onenote onetoc
+application/onenote onetoc2
+application/onenote onetmp
+application/onenote onepkg
+application/oxps oxps
+application/patch-ops-error+xml xer
+application/pdf pdf
+application/pgp-encrypted pgp
+application/pgp-signature asc
+application/pgp-signature sig
+application/pics-rules prf
+application/pkcs10 p10
+application/pkcs7-mime p7m
+application/pkcs7-mime p7c
+application/pkcs7-signature p7s
+application/pkcs8 p8
+application/pkix-attr-cert ac
+application/pkix-cert cer
+application/pkix-crl crl
+application/pkix-pkipath pkipath
+application/pkixcmp pki
+application/pls+xml pls
+application/postscript ai
+application/postscript eps
+application/postscript ps
+application/prs.cww cww
+application/pskc+xml pskcxml
+application/rdf+xml rdf
+application/reginfo+xml rif
+application/relax-ng-compact-syntax rnc
+application/resource-lists+xml rl
+application/resource-lists-diff+xml rld
+application/rls-services+xml rs
+application/rpki-ghostbusters gbr
+application/rpki-manifest mft
+application/rpki-roa roa
+application/rsd+xml rsd
+application/rss+xml rss
+application/rtf rtf
+application/sbml+xml sbml
+application/scvp-cv-request scq
+application/scvp-cv-response scs
+application/scvp-vp-request spq
+application/scvp-vp-response spp
+application/sdp sdp
+application/set-payment-initiation setpay
+application/set-registration-initiation setreg
+application/shf+xml shf
+application/smil+xml smi
+application/smil+xml smil
+application/sparql-query rq
+application/sparql-results+xml srx
+application/srgs gram
+application/srgs+xml grxml
+application/sru+xml sru
+application/ssdl+xml ssdl
+application/ssml+xml ssml
+application/tei+xml tei
+application/tei+xml teicorpus
+application/thraud+xml tfi
+application/timestamped-data tsd
+application/vnd.3gpp.pic-bw-large plb
+application/vnd.3gpp.pic-bw-small psb
+application/vnd.3gpp.pic-bw-var pvb
+application/vnd.3gpp2.tcap tcap
+application/vnd.3m.post-it-notes pwn
+application/vnd.accpac.simply.aso aso
+application/vnd.accpac.simply.imp imp
+application/vnd.acucobol acu
+application/vnd.acucorp atc
+application/vnd.acucorp acutc
+application/vnd.adobe.air-application-installer-package+zip air
+application/vnd.adobe.formscentral.fcdt fcdt
+application/vnd.adobe.fxp fxp
+application/vnd.adobe.fxp fxpl
+application/vnd.adobe.xdp+xml xdp
+application/vnd.adobe.xfdf xfdf
+application/vnd.ahead.space ahead
+application/vnd.airzip.filesecure.azf azf
+application/vnd.airzip.filesecure.azs azs
+application/vnd.amazon.ebook azw
+application/vnd.americandynamics.acc acc
+application/vnd.amiga.ami ami
+application/vnd.android.package-archive apk
+application/vnd.anser-web-certificate-issue-initiation cii
+application/vnd.anser-web-funds-transfer-initiation fti
+application/vnd.antix.game-component atx
+application/vnd.apple.installer+xml mpkg
+application/vnd.apple.mpegurl m3u8
+application/vnd.aristanetworks.swi swi
+application/vnd.astraea-software.iota iota
+application/vnd.audiograph aep
+application/vnd.blueice.multipass mpm
+application/vnd.bmi bmi
+application/vnd.businessobjects rep
+application/vnd.chemdraw+xml cdxml
+application/vnd.chipnuts.karaoke-mmd mmd
+application/vnd.cinderella cdy
+application/vnd.claymore cla
+application/vnd.cloanto.rp9 rp9
+application/vnd.clonk.c4group c4g
+application/vnd.clonk.c4group c4d
+application/vnd.clonk.c4group c4f
+application/vnd.clonk.c4group c4p
+application/vnd.clonk.c4group c4u
+application/vnd.cluetrust.cartomobile-config c11amc
+application/vnd.cluetrust.cartomobile-config-pkg c11amz
+application/vnd.commonspace csp
+application/vnd.contact.cmsg cdbcmsg
+application/vnd.cosmocaller cmc
+application/vnd.crick.clicker clkx
+application/vnd.crick.clicker.keyboard clkk
+application/vnd.crick.clicker.palette clkp
+application/vnd.crick.clicker.template clkt
+application/vnd.crick.clicker.wordbank clkw
+application/vnd.criticaltools.wbs+xml wbs
+application/vnd.ctc-posml pml
+application/vnd.cups-ppd ppd
+application/vnd.curl.car car
+application/vnd.curl.pcurl pcurl
+application/vnd.dart dart
+application/vnd.data-vision.rdz rdz
+application/vnd.dece.data uvf
+application/vnd.dece.data uvvf
+application/vnd.dece.data uvd
+application/vnd.dece.data uvvd
+application/vnd.dece.ttml+xml uvt
+application/vnd.dece.ttml+xml uvvt
+application/vnd.dece.unspecified uvx
+application/vnd.dece.unspecified uvvx
+application/vnd.dece.zip uvz
+application/vnd.dece.zip uvvz
+application/vnd.denovo.fcselayout-link fe_launch
+application/vnd.dna dna
+application/vnd.dolby.mlp mlp
+application/vnd.dpgraph dpg
+application/vnd.dreamfactory dfac
+application/vnd.ds-keypoint kpxx
+application/vnd.dvb.ait ait
+application/vnd.dvb.service svc
+application/vnd.dynageo geo
+application/vnd.ecowin.chart mag
+application/vnd.enliven nml
+application/vnd.epson.esf esf
+application/vnd.epson.msf msf
+application/vnd.epson.quickanime qam
+application/vnd.epson.salt slt
+application/vnd.epson.ssf ssf
+application/vnd.eszigno3+xml es3
+application/vnd.eszigno3+xml et3
+application/vnd.ezpix-album ez2
+application/vnd.ezpix-package ez3
+application/vnd.fdf fdf
+application/vnd.fdsn.mseed mseed
+application/vnd.fdsn.seed seed
+application/vnd.fdsn.seed dataless
+application/vnd.flographit gph
+application/vnd.fluxtime.clip ftc
+application/vnd.framemaker fm
+application/vnd.framemaker frame
+application/vnd.framemaker maker
+application/vnd.framemaker book
+application/vnd.frogans.fnc fnc
+application/vnd.frogans.ltf ltf
+application/vnd.fsc.weblaunch fsc
+application/vnd.fujitsu.oasys oas
+application/vnd.fujitsu.oasys2 oa2
+application/vnd.fujitsu.oasys3 oa3
+application/vnd.fujitsu.oasysgp fg5
+application/vnd.fujitsu.oasysprs bh2
+application/vnd.fujixerox.ddd ddd
+application/vnd.fujixerox.docuworks xdw
+application/vnd.fujixerox.docuworks.binder xbd
+application/vnd.fuzzysheet fzs
+application/vnd.genomatix.tuxedo txd
+application/vnd.geogebra.file ggb
+application/vnd.geogebra.tool ggt
+application/vnd.geometry-explorer gex
+application/vnd.geometry-explorer gre
+application/vnd.geonext gxt
+application/vnd.geoplan g2w
+application/vnd.geospace g3w
+application/vnd.gmx gmx
+application/vnd.google-earth.kml+xml kml
+application/vnd.google-earth.kmz kmz
+application/vnd.grafeq gqf
+application/vnd.grafeq gqs
+application/vnd.groove-account gac
+application/vnd.groove-help ghf
+application/vnd.groove-identity-message gim
+application/vnd.groove-injector grv
+application/vnd.groove-tool-message gtm
+application/vnd.groove-tool-template tpl
+application/vnd.groove-vcard vcg
+application/vnd.hal+xml hal
+application/vnd.handheld-entertainment+xml zmm
+application/vnd.hbci hbci
+application/vnd.hhe.lesson-player les
+application/vnd.hp-hpgl hpgl
+application/vnd.hp-hpid hpid
+application/vnd.hp-hps hps
+application/vnd.hp-jlyt jlt
+application/vnd.hp-pcl pcl
+application/vnd.hp-pclxl pclxl
+application/vnd.hydrostatix.sof-data sfd-hdstx
+application/vnd.ibm.minipay mpy
+application/vnd.ibm.modcap afp
+application/vnd.ibm.modcap listafp
+application/vnd.ibm.modcap list3820
+application/vnd.ibm.rights-management irm
+application/vnd.ibm.secure-container sc
+application/vnd.iccprofile icc
+application/vnd.iccprofile icm
+application/vnd.igloader igl
+application/vnd.immervision-ivp ivp
+application/vnd.immervision-ivu ivu
+application/vnd.insors.igm igm
+application/vnd.intercon.formnet xpw
+application/vnd.intercon.formnet xpx
+application/vnd.intergeo i2g
+application/vnd.intu.qbo qbo
+application/vnd.intu.qfx qfx
+application/vnd.ipunplugged.rcprofile rcprofile
+application/vnd.irepository.package+xml irp
+application/vnd.is-xpr xpr
+application/vnd.isac.fcs fcs
+application/vnd.jam jam
+application/vnd.jcp.javame.midlet-rms rms
+application/vnd.jisp jisp
+application/vnd.joost.joda-archive joda
+application/vnd.kahootz ktz
+application/vnd.kahootz ktr
+application/vnd.kde.karbon karbon
+application/vnd.kde.kchart chrt
+application/vnd.kde.kformula kfo
+application/vnd.kde.kivio flw
+application/vnd.kde.kontour kon
+application/vnd.kde.kpresenter kpr
+application/vnd.kde.kpresenter kpt
+application/vnd.kde.kspread ksp
+application/vnd.kde.kword kwd
+application/vnd.kde.kword kwt
+application/vnd.kenameaapp htke
+application/vnd.kidspiration kia
+application/vnd.kinar kne
+application/vnd.kinar knp
+application/vnd.koan skp
+application/vnd.koan skd
+application/vnd.koan skt
+application/vnd.koan skm
+application/vnd.kodak-descriptor sse
+application/vnd.las.las+xml lasxml
+application/vnd.llamagraphics.life-balance.desktop lbd
+application/vnd.llamagraphics.life-balance.exchange+xml lbe
+application/vnd.lotus-1-2-3 123
+application/vnd.lotus-approach apr
+application/vnd.lotus-freelance pre
+application/vnd.lotus-notes nsf
+application/vnd.lotus-organizer org
+application/vnd.lotus-screencam scm
+application/vnd.lotus-wordpro lwp
+application/vnd.macports.portpkg portpkg
+application/vnd.mcd mcd
+application/vnd.medcalcdata mc1
+application/vnd.mediastation.cdkey cdkey
+application/vnd.mfer mwf
+application/vnd.mfmp mfm
+application/vnd.micrografx.flo flo
+application/vnd.micrografx.igx igx
+application/vnd.mif mif
+application/vnd.mobius.daf daf
+application/vnd.mobius.dis dis
+application/vnd.mobius.mbk mbk
+application/vnd.mobius.mqy mqy
+application/vnd.mobius.msl msl
+application/vnd.mobius.plc plc
+application/vnd.mobius.txf txf
+application/vnd.mophun.application mpn
+application/vnd.mophun.certificate mpc
+application/vnd.mozilla.xul+xml xul
+application/vnd.ms-artgalry cil
+application/vnd.ms-cab-compressed cab
+application/vnd.ms-excel xls
+application/vnd.ms-excel xlm
+application/vnd.ms-excel xla
+application/vnd.ms-excel xlc
+application/vnd.ms-excel xlt
+application/vnd.ms-excel xlw
+application/vnd.ms-excel.addin.macroenabled.12 xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
+application/vnd.ms-excel.sheet.macroenabled.12 xlsm
+application/vnd.ms-excel.template.macroenabled.12 xltm
+application/vnd.ms-fontobject eot
+application/vnd.ms-htmlhelp chm
+application/vnd.ms-ims ims
+application/vnd.ms-lrm lrm
+application/vnd.ms-officetheme thmx
+application/vnd.ms-pki.seccat cat
+application/vnd.ms-pki.stl stl
+application/vnd.ms-powerpoint ppt
+application/vnd.ms-powerpoint pps
+application/vnd.ms-powerpoint pot
+application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
+application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
+application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
+application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
+application/vnd.ms-powerpoint.template.macroenabled.12 potm
+application/vnd.ms-project mpp
+application/vnd.ms-project mpt
+application/vnd.ms-word.document.macroenabled.12 docm
+application/vnd.ms-word.template.macroenabled.12 dotm
+application/vnd.ms-works wps
+application/vnd.ms-works wks
+application/vnd.ms-works wcm
+application/vnd.ms-works wdb
+application/vnd.ms-wpl wpl
+application/vnd.ms-xpsdocument xps
+application/vnd.mseq mseq
+application/vnd.musician mus
+application/vnd.muvee.style msty
+application/vnd.mynfc taglet
+application/vnd.neurolanguage.nlu nlu
+application/vnd.nitf ntf
+application/vnd.nitf nitf
+application/vnd.noblenet-directory nnd
+application/vnd.noblenet-sealer nns
+application/vnd.noblenet-web nnw
+application/vnd.nokia.n-gage.data ngdat
+application/vnd.nokia.n-gage.symbian.install n-gage
+application/vnd.nokia.radio-preset rpst
+application/vnd.nokia.radio-presets rpss
+application/vnd.novadigm.edm edm
+application/vnd.novadigm.edx edx
+application/vnd.novadigm.ext ext
+application/vnd.oasis.opendocument.chart odc
+application/vnd.oasis.opendocument.chart-template otc
+application/vnd.oasis.opendocument.database odb
+application/vnd.oasis.opendocument.formula odf
+application/vnd.oasis.opendocument.formula-template odft
+application/vnd.oasis.opendocument.graphics odg
+application/vnd.oasis.opendocument.graphics-template otg
+application/vnd.oasis.opendocument.image odi
+application/vnd.oasis.opendocument.image-template oti
+application/vnd.oasis.opendocument.presentation odp
+application/vnd.oasis.opendocument.presentation-template otp
+application/vnd.oasis.opendocument.spreadsheet ods
+application/vnd.oasis.opendocument.spreadsheet-template ots
+application/vnd.oasis.opendocument.text odt
+application/vnd.oasis.opendocument.text-master odm
+application/vnd.oasis.opendocument.text-template ott
+application/vnd.oasis.opendocument.text-web oth
+application/vnd.olpc-sugar xo
+application/vnd.oma.dd2+xml dd2
+application/vnd.openofficeorg.extension oxt
+application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
+application/vnd.openxmlformats-officedocument.presentationml.slide sldx
+application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
+application/vnd.openxmlformats-officedocument.presentationml.template potx
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
+application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
+application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
+application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
+application/vnd.osgeo.mapguide.package mgp
+application/vnd.osgi.dp dp
+application/vnd.osgi.subsystem esa
+application/vnd.palm pdb
+application/vnd.palm pqa
+application/vnd.palm oprc
+application/vnd.pawaafile paw
+application/vnd.pg.format str
+application/vnd.pg.osasli ei6
+application/vnd.picsel efif
+application/vnd.pmi.widget wg
+application/vnd.pocketlearn plf
+application/vnd.powerbuilder6 pbd
+application/vnd.previewsystems.box box
+application/vnd.proteus.magazine mgz
+application/vnd.publishare-delta-tree qps
+application/vnd.pvi.ptid1 ptid
+application/vnd.quark.quarkxpress qxd
+application/vnd.quark.quarkxpress qxt
+application/vnd.quark.quarkxpress qwd
+application/vnd.quark.quarkxpress qwt
+application/vnd.quark.quarkxpress qxl
+application/vnd.quark.quarkxpress qxb
+application/vnd.realvnc.bed bed
+application/vnd.recordare.musicxml mxl
+application/vnd.recordare.musicxml+xml musicxml
+application/vnd.rig.cryptonote cryptonote
+application/vnd.rim.cod cod
+application/vnd.rn-realmedia rm
+application/vnd.rn-realmedia-vbr rmvb
+application/vnd.route66.link66+xml link66
+application/vnd.sailingtracker.track st
+application/vnd.seemail see
+application/vnd.sema sema
+application/vnd.semd semd
+application/vnd.semf semf
+application/vnd.shana.informed.formdata ifm
+application/vnd.shana.informed.formtemplate itp
+application/vnd.shana.informed.interchange iif
+application/vnd.shana.informed.package ipk
+application/vnd.simtech-mindmapper twd
+application/vnd.simtech-mindmapper twds
+application/vnd.smaf mmf
+application/vnd.smart.teacher teacher
+application/vnd.solent.sdkm+xml sdkm
+application/vnd.solent.sdkm+xml sdkd
+application/vnd.spotfire.dxp dxp
+application/vnd.spotfire.sfs sfs
+application/vnd.stardivision.calc sdc
+application/vnd.stardivision.draw sda
+application/vnd.stardivision.impress sdd
+application/vnd.stardivision.math smf
+application/vnd.stardivision.writer sdw
+application/vnd.stardivision.writer vor
+application/vnd.stardivision.writer-global sgl
+application/vnd.stepmania.package smzip
+application/vnd.stepmania.stepchart sm
+application/vnd.sun.xml.calc sxc
+application/vnd.sun.xml.calc.template stc
+application/vnd.sun.xml.draw sxd
+application/vnd.sun.xml.draw.template std
+application/vnd.sun.xml.impress sxi
+application/vnd.sun.xml.impress.template sti
+application/vnd.sun.xml.math sxm
+application/vnd.sun.xml.writer sxw
+application/vnd.sun.xml.writer.global sxg
+application/vnd.sun.xml.writer.template stw
+application/vnd.sus-calendar sus
+application/vnd.sus-calendar susp
+application/vnd.svd svd
+application/vnd.symbian.install sis
+application/vnd.symbian.install sisx
+application/vnd.syncml+xml xsm
+application/vnd.syncml.dm+wbxml bdm
+application/vnd.syncml.dm+xml xdm
+application/vnd.tao.intent-module-archive tao
+application/vnd.tcpdump.pcap pcap
+application/vnd.tcpdump.pcap cap
+application/vnd.tcpdump.pcap dmp
+application/vnd.tmobile-livetv tmo
+application/vnd.trid.tpt tpt
+application/vnd.triscape.mxs mxs
+application/vnd.trueapp tra
+application/vnd.ufdl ufd
+application/vnd.ufdl ufdl
+application/vnd.uiq.theme utz
+application/vnd.umajin umj
+application/vnd.unity unityweb
+application/vnd.uoml+xml uoml
+application/vnd.vcx vcx
+application/vnd.visio vsd
+application/vnd.visio vst
+application/vnd.visio vss
+application/vnd.visio vsw
+application/vnd.visionary vis
+application/vnd.vsf vsf
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/vnd.webturbo wtb
+application/vnd.wolfram.player nbp
+application/vnd.wordperfect wpd
+application/vnd.wqd wqd
+application/vnd.wt.stf stf
+application/vnd.xara xar
+application/vnd.xfdl xfdl
+application/vnd.yamaha.hv-dic hvd
+application/vnd.yamaha.hv-script hvs
+application/vnd.yamaha.hv-voice hvp
+application/vnd.yamaha.openscoreformat osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
+application/vnd.yamaha.smaf-audio saf
+application/vnd.yamaha.smaf-phrase spf
+application/vnd.yellowriver-custom-menu cmp
+application/vnd.zul zir
+application/vnd.zul zirz
+application/vnd.zzazz.deck+xml zaz
+application/voicexml+xml vxml
+application/widget wgt
+application/winhlp hlp
+application/wsdl+xml wsdl
+application/wspolicy+xml wspolicy
+application/x-7z-compressed 7z
+application/x-abiword abw
+application/x-ace-compressed ace
+application/x-apple-diskimage dmg
+application/x-authorware-bin aab
+application/x-authorware-bin x32
+application/x-authorware-bin u32
+application/x-authorware-bin vox
+application/x-authorware-map aam
+application/x-authorware-seg aas
+application/x-bcpio bcpio
+application/x-bittorrent torrent
+application/x-blorb blb
+application/x-blorb blorb
+application/x-bzip bz
+application/x-bzip2 bz2
+application/x-bzip2 boz
+application/x-cbr cbr
+application/x-cbr cba
+application/x-cbr cbt
+application/x-cbr cbz
+application/x-cbr cb7
+application/x-cdlink vcd
+application/x-cfs-compressed cfs
+application/x-chat chat
+application/x-chess-pgn pgn
+application/x-conference nsc
+application/x-cpio cpio
+application/x-csh csh
+application/x-debian-package deb
+application/x-debian-package udeb
+application/x-dgc-compressed dgc
+application/x-director dir
+application/x-director dcr
+application/x-director dxr
+application/x-director cst
+application/x-director cct
+application/x-director cxt
+application/x-director w3d
+application/x-director fgd
+application/x-director swa
+application/x-doom wad
+application/x-dtbncx+xml ncx
+application/x-dtbook+xml dtb
+application/x-dtbresource+xml res
+application/x-dvi dvi
+application/x-envoy evy
+application/x-eva eva
+application/x-font-bdf bdf
+application/x-font-ghostscript gsf
+application/x-font-linux-psf psf
+application/x-font-pcf pcf
+application/x-font-snf snf
+application/x-font-type1 pfa
+application/x-font-type1 pfb
+application/x-font-type1 pfm
+application/x-font-type1 afm
+application/x-freearc arc
+application/x-futuresplash spl
+application/x-gca-compressed gca
+application/x-glulx ulx
+application/x-gnumeric gnumeric
+application/x-gramps-xml gramps
+application/x-gtar gtar
+application/x-hdf hdf
+application/x-install-instructions install
+application/x-iso9660-image iso
+application/x-java-jnlp-file jnlp
+application/x-latex latex
+application/x-lzh-compressed lzh
+application/x-lzh-compressed lha
+application/x-mie mie
+application/x-mobipocket-ebook prc
+application/x-mobipocket-ebook mobi
+application/x-ms-application application
+application/x-ms-shortcut lnk
+application/x-ms-wmd wmd
+application/x-ms-wmz wmz
+application/x-ms-xbap xbap
+application/x-msaccess mdb
+application/x-msbinder obd
+application/x-mscardfile crd
+application/x-msclip clp
+application/x-msdownload exe
+application/x-msdownload dll
+application/x-msdownload com
+application/x-msdownload bat
+application/x-msdownload msi
+application/x-msmediaview mvb
+application/x-msmediaview m13
+application/x-msmediaview m14
+application/x-msmetafile wmf
+application/x-msmetafile wmz
+application/x-msmetafile emf
+application/x-msmetafile emz
+application/x-msmoney mny
+application/x-mspublisher pub
+application/x-msschedule scd
+application/x-msterminal trm
+application/x-mswrite wri
+application/x-netcdf nc
+application/x-netcdf cdf
+application/x-nzb nzb
+application/x-pkcs12 p12
+application/x-pkcs12 pfx
+application/x-pkcs7-certificates p7b
+application/x-pkcs7-certificates spc
+application/x-pkcs7-certreqresp p7r
+application/x-rar-compressed rar
+application/x-research-info-systems ris
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-silverlight-app xap
+application/x-sql sql
+application/x-stuffit sit
+application/x-stuffitx sitx
+application/x-subrip srt
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-t3vm-image t3
+application/x-tads gam
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-tex-tfm tfm
+application/x-texinfo texinfo
+application/x-texinfo texi
+application/x-tgif obj
+application/x-ustar ustar
+application/x-wais-source src
+application/x-x509-ca-cert der
+application/x-x509-ca-cert crt
+application/x-xfig fig
+application/x-xliff+xml xlf
+application/x-xpinstall xpi
+application/x-xz xz
+application/x-zmachine z1
+application/x-zmachine z2
+application/x-zmachine z3
+application/x-zmachine z4
+application/x-zmachine z5
+application/x-zmachine z6
+application/x-zmachine z7
+application/x-zmachine z8
+application/xaml+xml xaml
+application/xcap-diff+xml xdf
+application/xenc+xml xenc
+application/xhtml+xml xhtml
+application/xhtml+xml xht
+application/xml xml
+application/xml xsl
+application/xml-dtd dtd
+application/xop+xml xop
+application/xproc+xml xpl
+application/xslt+xml xslt
+application/xspf+xml xspf
+application/xv+xml mxml
+application/xv+xml xhvml
+application/xv+xml xvml
+application/xv+xml xvm
+application/yang yang
+application/yin+xml yin
+application/zip zip
+audio/adpcm adp
+audio/basic au
+audio/basic snd
+audio/midi mid
+audio/midi midi
+audio/midi kar
+audio/midi rmi
+audio/mp4 m4a
+audio/mp4 mp4a
+audio/mpeg mpga
+audio/mpeg mp2
+audio/mpeg mp2a
+audio/mpeg mp3
+audio/mpeg m2a
+audio/mpeg m3a
+audio/ogg oga
+audio/ogg ogg
+audio/ogg spx
+audio/s3m s3m
+audio/silk sil
+audio/vnd.dece.audio uva
+audio/vnd.dece.audio uvva
+audio/vnd.digital-winds eol
+audio/vnd.dra dra
+audio/vnd.dts dts
+audio/vnd.dts.hd dtshd
+audio/vnd.lucent.voice lvp
+audio/vnd.ms-playready.media.pya pya
+audio/vnd.nuera.ecelp4800 ecelp4800
+audio/vnd.nuera.ecelp7470 ecelp7470
+audio/vnd.nuera.ecelp9600 ecelp9600
+audio/vnd.rip rip
+audio/webm weba
+audio/x-aac aac
+audio/x-aiff aif
+audio/x-aiff aiff
+audio/x-aiff aifc
+audio/x-caf caf
+audio/x-flac flac
+audio/x-matroska mka
+audio/x-mpegurl m3u
+audio/x-ms-wax wax
+audio/x-ms-wma wma
+audio/x-pn-realaudio ram
+audio/x-pn-realaudio ra
+audio/x-pn-realaudio-plugin rmp
+audio/x-wav wav
+audio/xm xm
+chemical/x-cdx cdx
+chemical/x-cif cif
+chemical/x-cmdf cmdf
+chemical/x-cml cml
+chemical/x-csml csml
+chemical/x-xyz xyz
+font/collection ttc
+font/otf otf
+font/ttf ttf
+font/woff woff
+font/woff2 woff2
+image/bmp bmp
+image/cgm cgm
+image/g3fax g3
+image/gif gif
+image/ief ief
+image/jpeg jpeg
+image/jpeg jpg
+image/jpeg jpe
+image/ktx ktx
+image/png png
+image/prs.btif btif
+image/sgi sgi
+image/svg+xml svg
+image/svg+xml svgz
+image/tiff tiff
+image/tiff tif
+image/vnd.adobe.photoshop psd
+image/vnd.dece.graphic uvi
+image/vnd.dece.graphic uvvi
+image/vnd.dece.graphic uvg
+image/vnd.dece.graphic uvvg
+image/vnd.djvu djvu
+image/vnd.djvu djv
+image/vnd.dvb.subtitle sub
+image/vnd.dwg dwg
+image/vnd.dxf dxf
+image/vnd.fastbidsheet fbs
+image/vnd.fpx fpx
+image/vnd.fst fst
+image/vnd.fujixerox.edmics-mmr mmr
+image/vnd.fujixerox.edmics-rlc rlc
+image/vnd.ms-modi mdi
+image/vnd.ms-photo wdp
+image/vnd.net-fpx npx
+image/vnd.wap.wbmp wbmp
+image/vnd.xiff xif
+image/webp webp
+image/x-3ds 3ds
+image/x-cmu-raster ras
+image/x-cmx cmx
+image/x-freehand fh
+image/x-freehand fhc
+image/x-freehand fh4
+image/x-freehand fh5
+image/x-freehand fh7
+image/x-icon ico
+image/x-mrsid-image sid
+image/x-pcx pcx
+image/x-pict pic
+image/x-pict pct
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-tga tga
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+message/rfc822 eml
+message/rfc822 mime
+model/iges igs
+model/iges iges
+model/mesh msh
+model/mesh mesh
+model/mesh silo
+model/vnd.collada+xml dae
+model/vnd.dwf dwf
+model/vnd.gdl gdl
+model/vnd.gtw gtw
+model/vnd.mts mts
+model/vnd.vtu vtu
+model/vrml wrl
+model/vrml vrml
+model/x3d+binary x3db
+model/x3d+binary x3dbz
+model/x3d+vrml x3dv
+model/x3d+vrml x3dvz
+model/x3d+xml x3d
+model/x3d+xml x3dz
+text/cache-manifest appcache
+text/calendar ics
+text/calendar ifb
+text/css css
+text/csv csv
+text/html html
+text/html htm
+text/n3 n3
+text/plain txt
+text/plain text
+text/plain conf
+text/plain def
+text/plain list
+text/plain log
+text/plain in
+text/prs.lines.tag dsc
+text/richtext rtx
+text/sgml sgml
+text/sgml sgm
+text/tab-separated-values tsv
+text/troff t
+text/troff tr
+text/troff roff
+text/troff man
+text/troff me
+text/troff ms
+text/turtle ttl
+text/uri-list uri
+text/uri-list uris
+text/uri-list urls
+text/vcard vcard
+text/vnd.curl curl
+text/vnd.curl.dcurl dcurl
+text/vnd.curl.mcurl mcurl
+text/vnd.curl.scurl scurl
+text/vnd.dvb.subtitle sub
+text/vnd.fly fly
+text/vnd.fmi.flexstor flx
+text/vnd.graphviz gv
+text/vnd.in3d.3dml 3dml
+text/vnd.in3d.spot spot
+text/vnd.sun.j2me.app-descriptor jad
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/x-asm s
+text/x-asm asm
+text/x-c c
+text/x-c cc
+text/x-c cxx
+text/x-c cpp
+text/x-c h
+text/x-c hh
+text/x-c dic
+text/x-fortran f
+text/x-fortran for
+text/x-fortran f77
+text/x-fortran f90
+text/x-java-source java
+text/x-nfo nfo
+text/x-opml opml
+text/x-pascal p
+text/x-pascal pas
+text/x-setext etx
+text/x-sfv sfv
+text/x-uuencode uu
+text/x-vcalendar vcs
+text/x-vcard vcf
+video/3gpp 3gp
+video/3gpp2 3g2
+video/h261 h261
+video/h263 h263
+video/h264 h264
+video/jpeg jpgv
+video/jpm jpm
+video/jpm jpgm
+video/mj2 mj2
+video/mj2 mjp2
+video/mp4 mp4
+video/mp4 mp4v
+video/mp4 mpg4
+video/mpeg mpeg
+video/mpeg mpg
+video/mpeg mpe
+video/mpeg m1v
+video/mpeg m2v
+video/ogg ogv
+video/quicktime qt
+video/quicktime mov
+video/vnd.dece.hd uvh
+video/vnd.dece.hd uvvh
+video/vnd.dece.mobile uvm
+video/vnd.dece.mobile uvvm
+video/vnd.dece.pd uvp
+video/vnd.dece.pd uvvp
+video/vnd.dece.sd uvs
+video/vnd.dece.sd uvvs
+video/vnd.dece.video uvv
+video/vnd.dece.video uvvv
+video/vnd.dvb.file dvb
+video/vnd.fvt fvt
+video/vnd.mpegurl mxu
+video/vnd.mpegurl m4u
+video/vnd.ms-playready.media.pyv pyv
+video/vnd.uvvu.mp4 uvu
+video/vnd.uvvu.mp4 uvvu
+video/vnd.vivo viv
+video/webm webm
+video/x-f4v f4v
+video/x-fli fli
+video/x-flv flv
+video/x-m4v m4v
+video/x-matroska mkv
+video/x-matroska mk3d
+video/x-matroska mks
+video/x-mng mng
+video/x-ms-asf asf
+video/x-ms-asf asx
+video/x-ms-vob vob
+video/x-ms-wm wm
+video/x-ms-wmv wmv
+video/x-ms-wmx wmx
+video/x-ms-wvx wvx
+video/x-msvideo avi
+video/x-sgi-movie movie
+video/x-smv smv
+x-conference/x-cooltalk ice
diff --git a/src/request.sh b/src/request.sh
new file mode 100644
index 0000000..2a9ac37
--- /dev/null
+++ b/src/request.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+[ -n "${HTTP_GUARD__REQUEST_SH+x}" ] && return
+export HTTP_GUARD__REQUEST_SH=''
+
+http::_parse_headers() {
+ read -r request_method request_path request_version
+
+ while read -r header_; do
+ [[ -z "${header_/$'\r'/}" ]] && break
+ local h_name h_value
+ IFS=: read -r h_name h_value <<< "${header_/': '/:}"
+ request_headers["${h_name}"]="${h_value}"
+ done
+}
+
+http::_parse_body() { cat - >/dev/null; } # TODO
+
+http::_route_request() {
+ [[ -z "${HTTP_SUPPORTED_METHODS[${request_method}]}" ]] && http::response 501 && return 1
+ local glob_endpoint handler path_found
+
+ for glob_endpoint in "${!http__all_routes[@]}"; do # FIXME O(n)
+ # shellcheck disable=SC2053
+ if [[ "${request_path}" == ${glob_endpoint} ]]; then
+ declare -rx HTTP_REQUEST_GLOB="${glob_endpoint}"
+ path_found=1
+ break
+ fi
+ done
+
+ handler="${http__handlers["$request_method,$glob_endpoint"]}"
+
+ if [[ -z "${path_found}" ]]; then
+ http::response 404; return 1
+ elif [[ -z "${handler}" ]]; then
+ http::response 405; return 1
+ else
+ "${handler}"
+ fi
+}
diff --git a/src/response.sh b/src/response.sh
new file mode 100644
index 0000000..12114b0
--- /dev/null
+++ b/src/response.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+[ -n "${HTTP_GUARD__RESPONSE_SH+x}" ] && return
+export HTTP_GUARD__RESPONSE_SH=''
+
+: "${HTTP_SCRIPT_PATH:="$(dirname "$(readlink -e "${BASH_SOURCE[0]:-$0}")")"}"
+readonly HTTP_SCRIPT_PATH
+
+declare -A mime_types
+
+while IFS=' ' read -r type ext; do
+ mime_types["$ext"]="$type"
+done < "$HTTP_SCRIPT_PATH/mime.types"
+
+
+# $1 = status code
+http::_response_base_headers() {
+ connection_string="${HTTP_PROTOCOL_VERSION} $1 ${HTTP_METHOD_NAMES["$1"]}"
+ : "${response_headers["Server"]:="${HTTP_SERVER_STRING}"}"
+ : "${response_headers["Connection"]:="close"}"
+ : "${response_headers["Date"]:="$(date -Ru)"}"
+ : "${response_headers["Cache-control"]:="no-cache"}"
+ : "${response_headers["Cache-control"]:="max-age=0"}"
+}
+
+
+# $1 = filename
+http::_response_content_headers() {
+ local type ext
+ response_headers["Content-Length"]="$(wc -c "$1" | cut -d ' ' -f 1)"
+
+ ext="$(cut -d '.' -f 2 <<< "$(basename "$1")")"
+ : "${response_headers["Content-Type"]:="${mime_types["$ext"]:-"$(file -ib "$1")"}"}"
+}
+
+
+http::_output_response_headers() {
+ echo "${connection_string}"
+ for header_name in "${!response_headers[@]}"; do
+ echo "${header_name}: ${response_headers[$header_name]}"
+ done
+ echo
+}
+
+
+# calle provides local -A response_headers
+# $1 = status code
+http::response() {
+ local status_code status_page
+ [[ -n "${HTTP_METHOD_NAMES["$1"]}" ]] && status_code="$1" || status_code="500"
+ status_page="$(http::_status_code_page "${status_code}")"
+ response_headers["Content-Type"]="text/html"
+ http::_response_base_headers "${status_code}"
+ http::_response_content_headers <(printf "%s" "${status_page}")
+ http::_output_response_headers
+ printf "%s" "${status_page}"
+}
+
+
+# calle provides local -A response_headers
+# $1 = filename
+http::file() {
+ [[ ! -f "$1" ]] && { http::response 500 && return 1; }
+ http::_response_base_headers "200"
+ http::_response_content_headers "$1"
+ http::_output_response_headers
+ cat "$1"
+}
+
+
+# calle provides local -A response_headers
+# $1 = filename
+http::html() { response_headers["Content-Type"]="text/html" http::file "$@"; }
diff --git a/src/tcp_server.sh b/src/tcp_server.sh
index 161c100..e4f0aa5 100644
--- a/src/tcp_server.sh
+++ b/src/tcp_server.sh
@@ -14,10 +14,10 @@ tcp::worker_() {
exec {socket_output}<> <(:)
# { nc -lknv -s "${host}" -p "${port}" > >( stdbuf -o0 sed "s/$delimiter/$delimiter_placeholder/g" ) 2> >( stdbuf -o0 sed "/Listening on.*/d;s/Connection received on /$delimiter/" >&2; ) ; } <&$socket_input >&$socket_output 2>&1 &
- {
+ {
socat "TCP-LISTEN:${host:-80},bind=${port:-127.0.0.1},fork,reuseport" \
> >( stdbuf -o0 sed "s/$delimiter/$delimiter_placeholder/g" ) \
- 2> >( stdbuf -o0 sed "/Listening on.*/d;s/Connection received on /$delimiter/" >&2; ) ;
+ 2> >( stdbuf -o0 sed "/Listening on.*/d;s/Connection received on /$delimiter/" >&2; ) ;
} <&$socket_input >&$socket_output 2>&1 &
echo "listenning"
@@ -35,7 +35,7 @@ tcp::worker_() {
printf "%s\n\n%s" "$(cat response.txt)" "$(cat index.html)" >&$socket_input # main logic
done
- exec {socket_input}<&-
+ exec {socket_input}<&-
exec {socket_output}<&-
}