HTTP to HTTPS redirect with awk

December 11, 2020

Why

Recently I had some down time and added HTTPS support to my blog. I'm currently using bozohttpd from xinetd. It works great for my low traffic blog. Unfortunately bozohttpd lacks real URL rewrite and redirect support.

I spent time looking for a simple tool to do the HTTP to HTTPS redirection, but apparently none exist. I looked up how to do proper 301 redirection is done and realized I could do it from awk. This is made easy since I'm already using xinetd. The redirect tool, i.e. awk, doesn't need to know anything about networking or sockets.

An Example HTTP Redirect

For reference a full exchange of a HTTP request and a redirect would look something like the following.

Client:

GET / HTTP/1.1
Host: erig.me

Server:

HTTP/1.1 301 Moved Permanently
Location: https://erig.me/

What it Looks Like

Here is my simple redirect script:

#!/usr/bin/env sh

exec unbuffer -p timeout 10 awk '
BEGIN {
        host = ""
        path = ""
}

/^GET/ {
        path = $2
}
/^Host:/ {
        host = $2
        print "HTTP/1.1 301 Moved Permanently"
        print "Location: " "https://" host path
        exit
}
'

The tricky bits here are:

  1. unbuffer
    • needed otherwise awk will hang waiting for enough data to fill the buffer which won't happen with the small amount in the HTTP request.
    • this tool is part of the expect package
  2. timeout 10
    • a safety net just in case the request lacks the Host: line. For non malicious requests this should only occur for HTTP/1.0, which no reasonable browser should be using.
  3. Why match Host?
    • This same webserver hosts multiple domains. As such we need to match Host: to redirect to the correct domain.

Lastly the xinetd configuration sits right next to my bozohttpd (https) configuration.

$ cat /etc/xinetd.d/httpd 
service http
{
        disable = no
        socket_type = stream
        protocol = tcp
        wait = no
        user = nobody
        server = /home/eric/www/awk_redirect
        instances = 300
        cps = 100 10
}

service https
{
        disable = no
        socket_type = stream
        protocol = tcp
        wait = no
        user = nobody
        server = /home/eric/bin/bozohttpd
        server_args = -v /home/eric/www /home/eric/www -Z /home/eric/www/certbot/etc/live/garver.life/fullchain.pem /home/eric/www/certbot/etc/live/garver.life/privkey.pem
        instances = 300
        cps = 100 10
}

Give it a Try

You can try this now. Here is the non SSL permalink for this post:

http://erig.me/blog/20201211/HTTP-to-HTTPS-redirect-with-awk.html

Is This Really a Good Idea?

For anything other than a low traffic blog... no. But it's simple and works well for my use case.

Previous Post