How to write a web server in bash script
Building a Web Server from Scratch with Bash Script
In the world of web development, the terms "web server" and "programming language" often go hand in hand. However, what if we told you that you could create a simple yet functional web server using nothing but a humble scripting language? In this article, we will explore an example for crafting a basic web server using Bash script, demonstrating the power of simplicity and resourcefulness.
The Basics of a Web Server
Before diving into the intricacies of a Bash-based web server, let's quickly recap what a web server is. At its core, a web server is software that handles incoming HTTP requests from clients (typically web browsers) and responds by serving the requested resources, such as HTML files, images, or other content. This process involves binding to a port, listening for incoming connections, and sending appropriate responses back to clients.
Building Bash Web Servers
Installation
Firstly we will install the dependencies required for this example. We will be using apache2 as web server, with the CGI module enabled. The Apache Common Gateway Interface (CGI) module is a crucial component of the Apache HTTP Server that facilitates the dynamic generation of web content by connecting external scripts and programs to the web server. Operating as an intermediary between the web server and these scripts, the CGI module enables the execution of various programming languages, such as Perl, Python, or Bash, in response to HTTP requests. When a client requests a dynamic resource, the CGI module invokes the relevant script or program, passing along necessary data and environmental variables. The output generated by the script is then formatted as an HTTP response and delivered to the requesting client.
We will use sqlite3 as database.
>sudo apt install sqlite3
>sudo apt install apache2
>sudo a2enmod cgi
>sudo service apache2 restart
Form
#!/bin/bash
echo "Content-type: text/html"
echo ""
cat <<EOT
<!DOCTYPE html>
<html>
<head>
<title>Welcome to our application</title>
</head>
<body>
<p>GET Form</p>
<br/>
<form action="get.sh" method="get">
<label>Name</label>
<input type="text" name="name">
<br>
<label>E-mail</label>
<input type="text" name="email">
<br>
<button type="submit">Submit</button>
</form>
<br/>
<p>POST Form</p>
<br/>
<form action="post.sh" method="post">
<label>Name</label>
<input type="text" name="name">
<br>
<label>E-mail</label>
<input type="text" name="email">
<br>
<button type="submit">Submit</button>
</form>
<br/>
<p>Cookies: $HTTP_COOKIE</p>
</body>
</html>
EOT
#!/bin/bash
name=`echo "$QUERY_STRING" | awk '{split($0,array,"&")} END{print array[1]}' | awk '{split($0,array,"=")} END{print array[2]}'`
email=`echo "$QUERY_STRING" | awk '{split($0,array,"&")} END{print array[2]}' | awk '{split($0,array,"=")} END{print array[2]}' | sed -e 's/%40/@/g'`
user_id=`sqlite3 app.db "select id from user where name = '$name';"`
if [ ! -n "$user_id" ]
then
sqlite3 app.db "insert into user (name, email) values ('$name', '$email');"
user_id=`sqlite3 app.db "select id from user where name = '$name';"`
fi
env_var=`env`
echo "Set-Cookie: user_id='$user_id'"
echo "Content-type: text/html"
echo ""
cat <<EOT
<!DOCTYPE html>
<html>
<head>
<title>Welcome to our application</title>
</head>
<body>
<h1>Welcome $name </h1>
<h2> Your e-mail address is $email <h2>
<br/>
<p>Cookies: $HTTP_COOKIE</p>
<br/>
<p>ENV: $env_var</p>
</body>
</html>
EOT
#!/bin/bash
read form
name=`echo "$form" | awk '{split($0,array,"&")} END{print array[1]}' | awk '{split($0,array,"=")} END{print array[2]}'`
email=`echo "$form" | awk '{split($0,array,"&")} END{print array[2]}' | awk '{split($0,array,"=")} END{print array[2]}' | sed -e 's/%40/@/g'`
user_id=`sqlite3 app.db "select id from user where name = '$name';"`
if [ ! -n "$user_id" ]
then
sqlite3 app.db "insert into user (name, email) values ('$name', '$email');"
user_id=`sqlite3 app.db "select id from user where name = '$name';"`
fi
env_var=`env`
echo "Set-Cookie: user_id='$user_id'"
echo "Content-type: text/html"
echo ""
cat <<EOT
<!DOCTYPE html>
<html>
<head>
<title>Welcome to our application</title>
</head>
<body>
<h1>Welcome $name </h1>
<h2> Your e-mail address is $email <h2>
<br/>
<p>Cookies: $HTTP_COOKIE</p>
<br/>
<p>ENV: $env_var</p>
</body>
</html>
EOT
Upload file
#!/bin/bash
echo "Content-type: text/html"
echo ""
cat <<EOT
<!DOCTYPE html>
<html>
<head>
<title>Welcome to our application</title>
</head>
<body>
<form action="fileup.sh" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<br>
<button type="submit">Submit</button>
</form>
</body>
</html>
EOT
#!/bin/bash
echo "Set-Cookie: user_id='$user_id'"
echo "Content-type: text/plain"
echo ""
TMPOUT=/home/al/tmp/test
cat > $TMPOUT
# Get the line count
LINES=$(wc -l $TMPOUT | cut -d ' ' -f 1)
# Remove the first four lines
tail -$((LINES - 4)) $TMPOUT >$TMPOUT.1
# Remove the last line
head -$((LINES - 5)) $TMPOUT.1 >$TMPOUT
Terminal
#!/bin/bash
read form
cmd=`echo "$form" | awk '{split($0,array,"&")} END{print array[1]}' | awk '{split($0,array,"=")} END{print array[2]}' | sed -e 's/+/ /g' | sed -e 's/\%2F/\//g' `
echo "Content-type: text/html"
echo ""
cat <<EOT
<!DOCTYPE html>
<html>
<head>
<title>Web terminal</title>
</head>
<body>
<textarea rows="50" cols="200">
$($cmd)
</textarea>
<br/>
<form action="terminal.sh" method="post">
<label>></label>
<input type="text" name="cmd">
<button type="submit">Run</button>
</form>
<br/>
</body>
</html>
EOT
Deployment
#!/bin/bash
echo "Creating database"
sqlite3 app/app.db "create table user (id INTEGER PRIMARY KEY, name TEXT, email TEXT);"
echo "Database created"
echo "Deploying app"
sudo cp -r scripts /usr/lib/cgi-bin
sudo chmod 777 -R /usr/lib/cgi-bin/scripts
echo "Done"
Testing the examples
http://localhost/cgi-bin/scripts/index.sh
>tailf /var/log/apache2/error.log
Conclusion
Crafting a web server from scratch using Bash scripting is just an exercise of curiosity to understand how the old CGI applications worked. While this approach might not be suitable for production-grade applications, it offers an excellent learning opportunity for understanding the fundamental principles of web servers, networking, and HTTP. By experimenting with Bash scripting, you can gain a deeper appreciation for the intricate processes that power the web.