bURL - A Pure Bash HTTP Client

Published on

This weekend’s silly project is bURL, a trivial HTTP client implemented in pure GNU Bash script. It’s been inspired by shudder’s guide to network programming in bash – unfortunately disappeared from the known internet, but you can still read it on archive.org.

The initial goal to reach was to be able to download a file in a basic Linux environment without using cURL, wget or even Netcat. I started to wonder if it could be done in pure Bash script – especially since I found out about Bash’s network socket capabilities –, without even calling a local UNIX command such as cat or grep.

This exercise is also a nice refresher about one of the most basic shell notions: redirections. Here is a breakdown of the script’s inner mechanism.

Quick reminder: on most UNIX systems, a process gets 3 standard file descriptors opened by the shell is it executed in. Those FD are:

First, we open a TCP/IP network socket to host baha.mu on port 80 tied to a new file descriptor (3); this FD is opened bidirectionally, since we’ll use it both to send a HTTP request to and read the response from:

exec 3<>/dev/tcp/baha.mu/80

Then we send a HTTP request to this FD…

printf "GET / HTTP/1.1\nHost: baha.mu\nUser-Agent: bURL/Bash ${BASH_VERSION}\n\n" >&3

…and we read the response that has been returned by the HTTP server from the same FD and write it to the standard input FD (0):

IFS=
while read -r -t 1 line 0<&3; do
    line=${line//$'\r'}
    echo "$line"
done

Finally, we close the network connection to the HTTP server:

exec 3<&-

Observations:

The code is available on Github.