Posted by mcortese on Mon 13 Mar 2006 at 07:25
Suppose you want to experiment a little with web pages and CGI's, but you don't want the hassle of installing the full Apache package. This quick and dirty shell script could just be what you need.
Put simply, a web server is an application that sends local text files over the network to the clients that request them. If you let another program (for example inetd) deal with the network part, the web server could be reduced to a mere cat "$filename" to stdout. Of course, the difficult part would be to extract that filename out of the HTTP request string: nothing that a Bash script cannot easily do!
The script
Step 1: Our script begins like any other scripts. The Bash magic, plus some definitions:
#!/bin/bash base=/var/www
Step 2: The inetd will feed our script with the data received from the remote host, the first row being the standard HTTP request, followed by zero or more header lines. Let's record the request and discard the rest:
read request while /bin/true; do read header [ "$header" == $'\r' ] && break; done
Step 3 (the tricky part): extract the URL from the request string and locate the document on the local file system:
url="${request#GET }"
url="${url% HTTP/*}"
filename="$base$url"
Step 4 (the heart of the script): send the file (if it exists) with a leading standard header:
if [ -f "$filename" ]; then
echo -e "HTTP/1.1 200 OK\r"
echo -e "Content-Type: `/usr/bin/file -bi \"$filename\"`\r"
echo -e "\r"
cat "$filename"
echo -e "\r"
else
echo -e "HTTP/1.1 404 Not Found\r"
echo -e "Content-Type: text/html\r"
echo -e "\r"
echo -e "404 Not Found\r"
echo -e "Not Found
The requested resource was not found\r"
echo -e "\r"
fi
That's all.
Installation
To make it work, you must add the following line to your /etc/inetd.conf file:
www stream tcp nowait nobody /usr/local/bin/webd webdwhere webd is the name you gave to the script.
After instructing inetd to re-read its configuration with /etc/init.d/inetd restart, you are ready to test it. Make the directory /var/www, place some HTML files in it, fire up your favourite web browser and try the URL http://localhost/FILENAME.html
Please note that this installation is not a wise thing to do if your computer is connected an insecure network, because you are exposing your hard disk contents to anyone who can establish a connection with your port 80. A better idea would be to use the tcpd wrapper and only allow local connections. I'll leave the implementation details to your imagination!
What about CGI's?
Put like this, this web server is pretty useless: it does not do anything more than you could already do simply pointing your web browser to a local file. We need support for (very simple) CGI's.
Theory: instead of sending a text file over the network, we run an executable file and send its output. Before doing that, we have to decode a little further the HTTP request, building a variable called QUERY_STRING that we must export to the executable.
Practice: in the above script, replace Step 3 with this slightly less trivial version:
url="${request#GET }"
url="${url% HTTP/*}"
query="${url#*\?}"
url="${url%%\?*}"
filename="$base$url"
if [ "$query" != "$url" -a -x "$filename" ]; then
export QUERY_STRING="$query"
echo -e "HTTP/1.1 200 OK\r"
"$filename"
echo -e "\r"
exit 0
fi
Of course this overly simplified web server cannot even be compared to application the size and complexity of Apache. It is just a hack!
This article can be found online at the Debian Administration website at the following bookmarkable URL (along with associated comments):
This article is copyright 2006 mcortese - please ask for permission to republish or translate.