blob: 314ed52bc4b0d46a6f2dc70c43de9451e526d46a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
#! /bin/sh
# vim:set fdm=marker:
set -euf
Server='htgen-plain/1.0'
## htgen --serve {{{
case $# in
(1)
case "$1" in
(--serve)
HTGEN_HOST="${HTGEN_HOST-0.0.0.0}"
HTGEN_PORT="${HTGEN_PORT-42380}"
TCPSERVER_OPTS='-c 423 -t 2 -D'
echo "#### $Server $HTGEN_HOST:$HTGEN_PORT" >&2
exec tcpserver $TCPSERVER_OPTS "$HTGEN_HOST" "$HTGEN_PORT" "$0"
## this should not happen...
exit 23
esac
esac
## }}}
## reply_404 {{{
reply_404() {
cat<<EOF
HTTP/1.0 404 Not Found
Content-Type: text/plain; charset=UTF-8
Server: $Server
Connection: close
Content-Length: 0
EOF
}
## }}}
## date. {{{
#date=`date --rfc-3339=ns`
date="`date '+%Y-%m-%d %H:%M:%S'`"
cat>&2<<EOF
# ${TCPREMOTEHOST-}[$TCPREMOTEIP]:$TCPREMOTEPORT connected at $date over $PROTO
EOF
## }}}
## Parse Request-Line. {{{
read Request_Line
eval "$(echo "$Request_Line" | sed -rn '
s^([a-zA-Z]+) ([a-zA-Z0-9?&+*/.-]+) HTTP/([0-9]+\.[0-9]+)\r$\
Request_Line="&"\
Method="\1"\
Request_URI="\2"\
HTTP_Version="\3"\
p;t;i\
Request_Line= # invalid request
')"
#echo "Request-Line: $Request_Line" >&2
# cat>&2<<EOF
# Request_Line='$Request_Line'
# Method='$Method'
# Request_URI='$Request_URI'
# HTTP_Version='$HTTP_Version'
# EOF
## debug
cat>&2<<EOF
[1;33m$Method[m [1;4;34m$Request_URI[m HTTP/$HTTP_Version
EOF
## }}}
## Parse HTTP-Headers. {{{
# TODO support https://tools.ietf.org/html/rfc7230#section-3.2.4, obs-fold?
# TODO allow headers to appear multiple times
k=
v=
while read -r line; do
line=${line%
}
case $line in
'')
break
;;
[A-Za-z][0-9A-Za-z-]*:*)
k=${line%%:*}
k=${k//-/_}
k=${k,,}
k=req_$k
v=${line#*: }
v=${v## }
printf '[35m%s=[1m%s[m\n' "$k" "$v" >&2
export "$k=$v"
;;
esac
done
unset k v
echo >&2
## }}}
# run server: STATEDIR=/tmp/htgen-state HTGEN_PORT=1080 ./htgen --serve
# paste: echo lol | curl http://localhost:1080 -d @-
case "$Method $Request_URI" in
"GET /"[0-9a-z]*)
item=$STATEDIR/items$Request_URI
if test -e $item; then
printf 'HTTP/1.1 200 OK\r\n'
printf 'Content-Type: %s\r\n' "$(file -ib $item)"
printf 'Server: %s\r\n' "$Server"
printf 'Connection: close\r\n'
printf 'Content-Length: %d\r\n' $(wc -c < $item)
printf '\r\n'
cat $item
exit
fi
;;
"POST /")
content=$(mktemp -t htgen.$$.content.XXXXXXXX)
trap "rm $content >&2" EXIT
case ${req_expect-} in 100-continue)
printf 'HTTP/1.1 100 Continue\r\n\r\n'
esac
head -c $req_content_length > $content
sha256=$(sha256sum -b $content | cut -d\ -f1)
base32=$(nix-hash --to-base32 --type sha256 $sha256)
item=$STATEDIR/items/$base32
ref=http://$req_host/$base32
if ! test -e $item; then
mkdir -v -p $STATEDIR/items >&2
cp -v $content $item >&2
fi
printf 'HTTP/1.1 200 OK\r\n'
printf 'Content-Type: text/plain; charset=UTF-8\r\n'
printf 'Server: %s\r\n' "$Server"
printf 'Connection: close\r\n'
printf 'Content-Length: %d\r\n' $(expr ${#ref} + 1)
printf '\r\n'
printf '%s\n' "$ref"
exit
;;
esac
reply_404
exit
|