How I Do Redirects with Nginx and Test Them with Python

I needed a way to easily and quickly define lots of redirects for my blog. In this post I want to present my solution.

First a .map file has to be created. Each line represents one redirect and should have the following format FROM TO;. It's important to end each line with a ;.

/posts /blog;
/en/blog /blog;
/en/todo.html /blog/todo;

The nginx server configuration should look like this.

map_hash_bucket_size 256;

map $uri $redirected_url {
default "none";
include /etc/nginx/redirects.map;
}

server {
# ...
if ($redirected_url != "none") {
return 301 $redirected_url;
}
# ...
}

This Python script can be used to test the redirects. It loads each line of the redirects.map, makes a request to it and checks whether it redirected correctly.

import requests
from urllib.parse import urljoin

class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'

base = 'https://malura.de'

redirect_count = 0
redirect_success_count = 0

with open('redirects.map') as fp:
for cnt, line in enumerate(fp):
redirect_count += 1
[url, redirect] = [urljoin(base, chunk.strip().replace(';', '')) for chunk in line.split(' ')]
r = requests.get(url, allow_redirects=False)

redirected_location = r.headers['Location']
if redirected_location != redirect:
print("{} -> {} = {}".format(url, redirect, redirected_location))
else:
redirect_success_count += 1

if redirect_success_count != redirect_count:
print(f"{bcolors.FAIL}{redirect_count - redirect_success_count} redirects didnt work{bcolors.ENDC}")