-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.sh
executable file
·112 lines (103 loc) · 2.55 KB
/
server.sh
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
#!/bin/bash
set -e
ADDR=127.0.0.1
PORT=1234
ROOT="$(realpath "${1:-$PWD}")"
LF=$'\n'
tmpdir="$(mktemp -d)"
trap 'rm -r "$tmpdir"' EXIT
trap 'exit' INT
stdhead() {
code="$1"
head="$2"
echo "HTTP/1.0 $code $head"
echo "Content-Type: text/plain"
echo "Connection: close"
}
error() {
code="$1"
head="$2"
message="$3"
echo "HTTP/1.0 $code $head"
echo "Content-Type: text/plain"
echo "Connection: close"
echo
echo "$code $head"
echo
echo "$message"
exit
}
handle() {
connection_id="$1"
response_pipe="$tmpdir/response-$connection_id.pipe"
event_pipe="$tmpdir/event-$connection_id.pipe"
mkfifo -m 0600 "$response_pipe" "$event_pipe"
gnetcat -c -l "$ADDR" -p "$PORT" < "$response_pipe" | sed -E -u 's/\r$//' | (
read method url version || {
echo "Connection broken" > "$event_pipe"
exit
}
cat >& /dev/null & # read but ignore headers and whatever else
echo "$method $url" > "$event_pipe"
if ! [ "$version" = "HTTP/1.0" -o "$version" = "HTTP/1.1" ]; then
error 505 'HTTP Version Not Supported' "Version $version is not supported.${LF}Only 1.0 is really supported."
fi
if ! [ "$method" = "GET" ]; then
error 501 'Not Implemented' "Method $method is not implemented.${LF}Only GET is supported."
fi
if ! echo "$url" | grep -q '^/'; then
error 400 'Bad Request' "URL must be host-relative"
fi
if echo "$url" | grep -q '/\.'; then
error 403 'Forbidden' "Dot-files are forbidden"
fi
target="$ROOT$url"
name=$(basename "$url")
if [ -f "$target" ]; then
echo "HTTP/1.0 200 OK"
echo "Connection: close"
echo
cat "$target"
exit
fi
if [ -d "$target" ]; then
if ! echo "$url" | grep -q '/$'; then
echo "HTTP/1.0 307 Temporary Redirect"
echo "Connection: close"
echo "Location: $url/"
exit
fi
ls "$target" 2>/dev/null | {
echo "HTTP/1.0 200 OK"
echo "Content-Type: text/html; charset=utf-8"
echo "Connection: close"
echo
echo "<!DOCTYPE html>"
echo "<title>Directory listing for $url</title>"
echo "<h1>$name</h1>"
echo "<p><a href=\"..\">up</a>"
echo "<ul>"
while read entry; do
if [ -d "$target$entry" ]; then
entry="$entry/";
elif [ -f "$target$entry" ]; then
true
else
continue
fi
echo "<li><a href=\"$entry\">$entry</a>"
done
echo "</ul>"
} || error 403 'Forbidden' "Permission denied for $url"
exit
fi
error 404 'Not Found' "Requested file $url is not found"
) > "$response_pipe" &
rm "$response_pipe"
cat "$event_pipe"
rm "$event_pipe"
}
echo "Serving $ROOT"
for((i=0;;i++)); do
handle $i
done