mirror of
https://github.com/omar-polo/gmid.git
synced 2024-09-30 06:21:19 +02:00
c836cdfadb
the 1024 bytes limits is for the META only, not for the whole response. That means that the maximum size for the header line is 1029!
307 lines
7.5 KiB
Bash
Executable File
307 lines
7.5 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
set -e
|
|
|
|
ggflags=
|
|
|
|
# usage: config <global config> <stuff for localhost>
|
|
# generates a configuration file reg.conf
|
|
config() {
|
|
cat <<EOF > reg.conf
|
|
ipv6 off
|
|
port 10965
|
|
$1
|
|
server "localhost" {
|
|
cert "$PWD/cert.pem"
|
|
key "$PWD/key.pem"
|
|
root "$PWD/testdata"
|
|
$2
|
|
}
|
|
EOF
|
|
}
|
|
|
|
checkconf() {
|
|
./../gmid -n -c reg.conf
|
|
}
|
|
|
|
# usage: get <path>
|
|
# return the body of the request on stdout
|
|
get() {
|
|
./../gg -b $ggflags "gemini://localhost:10965/$1"
|
|
}
|
|
|
|
# usage: head <path>
|
|
# return the meta response line on stdout
|
|
head() {
|
|
./../gg -h $ggflags "gemini://localhost:10965/$1"
|
|
}
|
|
|
|
# usage: raw <path>
|
|
# return both header and body
|
|
raw() {
|
|
./../gg $ggflags "gemini://localhost:10965/$1"
|
|
}
|
|
|
|
run() {
|
|
./../gmid -f -c reg.conf &
|
|
pid=$!
|
|
# give gmid time to bind the port, otherwise we end up
|
|
# executing gg when gmid isn't ready yet.
|
|
sleep 1
|
|
}
|
|
|
|
# usage: check [exit-message]
|
|
# check if gmid is still running
|
|
check() {
|
|
if ! ps $pid >/dev/null; then
|
|
echo ${1:-"gmid crashed?"}
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
restart() {
|
|
kill -HUP $pid
|
|
sleep 1
|
|
}
|
|
|
|
# quit gmid
|
|
quit() {
|
|
kill $pid || true
|
|
wait || true
|
|
}
|
|
|
|
count() {
|
|
wc -l | xargs
|
|
}
|
|
|
|
# usage: eq a b errmsg
|
|
# if a and b aren't equal strings, exit with errmsg
|
|
eq() {
|
|
if ! [ "$1" = "$2" ]; then
|
|
echo "$3: \"$1\" not equal \"$2\""
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
onexit() {
|
|
rm -f bigfile bigfile.sha
|
|
quit
|
|
}
|
|
|
|
# tests
|
|
|
|
trap 'onexit' INT TERM EXIT
|
|
|
|
endl=`printf "\r\n"`
|
|
lf=`echo`
|
|
|
|
config "" ""
|
|
checkconf
|
|
run
|
|
|
|
eq "$(head /)" "20 text/gemini" "Unexpected head for /"
|
|
eq "$(get /)" "# hello world$ln" "Unexpected body for /"
|
|
echo OK GET /
|
|
|
|
eq "$(head /foo)" "51 not found" "Unexpected head /foo"
|
|
eq "$(get /foo)" "" "Unexpected body /foo"
|
|
echo OK GET /foo
|
|
|
|
# should redirect if asked for a directory but without the trailing /
|
|
eq "$(head /dir)" "30 /dir/" "Unexpected redirect for /dir"
|
|
eq "$(get /dir)" "" "Unexpected body for redirect"
|
|
echo OK GET /dir
|
|
|
|
# 51 for a directory without index.gmi
|
|
eq "$(head /dir/)" "51 not found" "Unexpected head for /"
|
|
eq "$(get /dir/)" "" "Unexpected body for error"
|
|
echo OK GET /dir/
|
|
|
|
eq "$(head /dir/foo.gmi)" "20 text/gemini" "Unexpected head for /dir/foo.gmi"
|
|
eq "$(get /dir/foo.gmi)" "# hello world$ln" "Unexpected body for /dir/foo.gmi"
|
|
echo OK GET /dir/foo.gmi
|
|
|
|
# try a big file
|
|
eq "$(head /bigfile)" "20 application/octet-stream" "Unexpected head for /bigfile"
|
|
get /bigfile > bigfile
|
|
./sha bigfile bigfile.sha
|
|
eq "$(cat bigfile.sha)" "$(cat testdata/bigfile.sha)" "Unexpected sha for /bigfile"
|
|
echo OK GET /bigfile
|
|
|
|
# shouldn't be executing cgi scripts
|
|
eq "$(head /hello)" "20 application/octet-stream" "Unexpected head for /hello"
|
|
echo OK GET /hello
|
|
|
|
check "should be running"
|
|
|
|
# try with custom mime
|
|
config 'mime "text/x-funny-text" "gmi"' 'default type "application/x-trash"'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /)" "20 text/x-funny-text" "Unexpected head for /"
|
|
echo OK GET / with custom mime
|
|
|
|
eq "$(head /hello)" "20 application/x-trash" "Unexpected head for /hello"
|
|
echo OK GET /hello with custom mime
|
|
|
|
check "should be running"
|
|
|
|
# try with custom lang
|
|
config '' 'lang "it"'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /)" "20 text/gemini; lang=it" "Unexpected head for /"
|
|
echo OK GET / with custom lang
|
|
|
|
check "should be running"
|
|
|
|
# make sure we can use different lang in different location rules
|
|
config '' 'lang "it" location "/en/*" { lang "en" } location "/de/*" { lang "de" }'
|
|
checkconf
|
|
echo OK parse multiple locations correctly
|
|
restart
|
|
|
|
# try with CGI scripts
|
|
config '' 'cgi "*"'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /hello)" "20 text/gemini" "Unexpected head for /hello"
|
|
eq "$(get /hello)" "# hello world$ln" "Unexpected body for /hello"
|
|
echo OK GET /hello with cgi
|
|
|
|
eq "$(head /slow)" "20 text/gemini" "Unexpected head for /slow"
|
|
eq "$(get /slow)" "# hello world$ln" "Unexpected body for /slow"
|
|
echo OK GET /slow with cgi
|
|
|
|
eq "$(head /err)" "42 CGI error" "Unexpected head for /err"
|
|
eq "$(get /err)" "" "Unexpected body for /err"
|
|
echo OK GET /err with cgi
|
|
|
|
eq "$(raw /invalid | wc -c | xargs)" 2048 "Unexpected body for /invalid"
|
|
echo OK GET /invalid with cgi
|
|
|
|
eq "$(raw /max-length-reply | wc -c | xargs)" 1029 "Unexpected header for /max-length-reply"
|
|
echo OK GET /max-length-reply with cgi
|
|
|
|
# try a big file
|
|
eq "$(head /serve-bigfile)" "20 application/octet-stream" "Unexpected head for /serve-bigfile"
|
|
get /bigfile > bigfile
|
|
./sha bigfile bigfile.sha
|
|
eq "$(cat bigfile.sha)" "$(cat testdata/bigfile.sha)" "Unexpected sha for /serve-bigfile"
|
|
echo OK GET /serve-bigfile with cgi
|
|
|
|
# ensure we split the query correctly
|
|
eq "$(get /env | awk /^-/ | count)" 1 "Unexpected number of arguments"
|
|
eq "$(get /env?foo | awk /^-/ | count)" 2 "Unexpected number of arguments"
|
|
eq "$(get /env?foo+bar | awk /^-/ | count)" 3 "Unexpected number of arguments"
|
|
eq "$(get /env?foo+bar=5 | awk /^-/ | count)" 1 "Unexpected number of arguments"
|
|
eq "$(get /env?foo+bar%3d5 | awk /^-/ | count)" 3 "Unexpected number of arguments"
|
|
|
|
check "should be running"
|
|
|
|
config '' 'index "foo.gmi"'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /dir/)" "20 text/gemini" "Unexpected head for /"
|
|
eq "$(get /dir/)" "# hello world$ln" "Unexpected body for error"
|
|
echo OK GET /dir/ with custom index
|
|
|
|
check "should be running"
|
|
|
|
config '' 'location "/dir/*" { default type "text/plain" index "hello" }'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /dir/hello)" "20 text/plain" "Unexpected head for /"
|
|
echo OK GET /dir/hello with location and default type
|
|
|
|
eq "$(head /dir/)" "20 text/plain" "Unexpected head for /dir/"
|
|
eq "$(get /dir/|tail -1)" 'echo "# hello world"' "Unexpected body for /dir/"
|
|
echo OK GET /dir/ with location and custom index
|
|
|
|
check "should be running"
|
|
|
|
config '' 'location "/dir/*" { auto index on }'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /)" "20 text/gemini" "Unexpected head for /"
|
|
eq "$(get /)" "# hello world$ln" "Unexpected body for /"
|
|
echo OK GET / with auto index
|
|
|
|
eq "$(head /dir)" "30 /dir/" "Unexpected head for /dir"
|
|
eq "$(head /dir/)" "20 text/gemini" "Unexpected head for /dir/"
|
|
eq "$(get /dir/|wc -l|xargs)" "5" "Unexpected body for /dir/"
|
|
echo OK GET /dir/ with auto index on
|
|
|
|
check "should be running"
|
|
|
|
# test block return and strip
|
|
|
|
config '' 'location "*" { block }'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /)" "40 temporary failure" "Unexpected head for /"
|
|
eq "$(get /)" "" "Unexpected body for /"
|
|
echo OK GET / with block
|
|
|
|
eq "$(head /nonexists)" "40 temporary failure" "Unexpected head for /nonexists"
|
|
eq "$(get /nonexists)" "" "Unexpected body for /nonexists"
|
|
echo OK GET /nonexists with block
|
|
|
|
check "should be running"
|
|
|
|
config '' '
|
|
location "/dir" {
|
|
strip 1
|
|
block return 40 "%% %p %q %P %N test"
|
|
}
|
|
location "*" {
|
|
strip 99
|
|
block return 40 "%% %p %q %P %N test"
|
|
}'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /dir/foo.gmi)" "40 % /foo.gmi 10965 localhost test"
|
|
echo OK GET /dir/foo.gmi with strip and block
|
|
|
|
eq "$(head /bigfile)" "40 % 10965 localhost test"
|
|
echo OK GET /bigfile with strip and block
|
|
|
|
check "should be running"
|
|
|
|
# test the entrypoint
|
|
|
|
config '' 'entrypoint "/env"'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /foo/bar)" "20 text/plain; lang=en" "Unknown head for /foo/bar"
|
|
eq "$(get /foo/bar|grep PATH_INFO)" "PATH_INFO=/foo/bar" "Unexpected PATH_INFO"
|
|
echo OK GET /foo/bar with entrypoint
|
|
|
|
# test with require ca
|
|
|
|
config '' 'require client ca "'$PWD'/testca.pem"'
|
|
checkconf
|
|
restart
|
|
|
|
eq "$(head /)" "60 client certificate required" "Unexpected head for /"
|
|
echo OK GET / without client certificate
|
|
|
|
ggflags="-C valid.crt -K valid.key"
|
|
eq "$(head /)" "20 text/gemini" "Unexpected head for /"
|
|
echo OK GET / with valid client certificate
|
|
|
|
ggflags="-C invalid.cert.pem -K invalid.key.pem"
|
|
eq "$(head /)" "61 certificate not authorised" "Unexpected head for /"
|
|
echo OK GET / with invalid client certificate
|
|
|
|
ggflags=''
|