On Apache servers, a RedirectMap
may be used to import bulk redirects. This provides an ideal solution for creating a self-hosted short URL service for any website, particularly static sites generated with Jekyll.
To implement a URL shortener using Jekyll and Apache, begin by simply adding a new key (e.g. shorturl
) to the front matter of any relevant posts. For example:
---
shorturl: example
---
Next, create a new file (e.g. shorturls.txt
) which contains the following liquid
code:
{% for post in site.posts %}{% if post.shorturl %}{{ post.shorturl }} {{ site.url }}{{ post.url }}
{% endif %}{% endfor %}{% for page in site.pages %}{% if page.shorturl %}{{ page.shorturl }} {{ site.url }}{{ page.url | remove: "index.html" }}
{% endif %}{% endfor %}
Build the site. Once the site is built, a new text file should exist resembling the following:
example https://www.example.com/this-is-an-example
Once the redirect map file is created, instruct Apache to use the file by adding the RedirectMap
to the Apache configuration (typically in httpd.conf
, or an included vhost
) by using the following:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# IMPORTANT: Make sure this file exists
# RewriteMap shorturl txt:/path/to/shorturls.txt
RewriteMap shorturl dbm:/path/to/shorturls.map
# URL shortener with fallback
RewriteRule ^(.*)$ ${shorturl:$1|https://example.com/$1} [R=302,L]
</IfModule>
Note: The RewriteRule
above uses 302
redirects when redirecting, and allows non-existent paths to fall through/fallback to the unshortened URL.
This may be setup on a primary domain (which may introduce conflicts as new URLs are created), or this may be setup on a secondary domain (e.g. short domain) or subdomain to reduce the possibility of naming collisions.
It may be desirable to prevent direct access to the redirect map file; this can be accomplished with a simple RedirectRule
:
# Disable direct access to short URL map
RewriteCond %{REQUEST_URI} ^/shorturls\. [NC]
RewriteRule ^ - [R=404]
Faster Redirects with DBM files
As the number of redirects grows, this solution may become slower (though the number of redirects would need to be very large). In any case, the httxt2dbm
command can be used to create dbm
files for use with RewriteMap
. A dbm
database file contains key/value pairs which map the redirect data; this works exactly the same way as a txt
map, but it is much faster, because the dbm
file is indexed. Rather than processing each line of the file until a match is found (which happens for txt
files), the dbm
file allows Apache to jump right to the relevant entry. This can greatly improve performance for large data sets.
httxt2dbm -i shorturls.txt -o shorturls.map
Note that with some dbm types, more than one file is generated, with a common base name. For example, you may have two files named mapfile.map.dir and mapfiile.map.pag. This is normal, and you need only use the base name mapfile.map in your RewriteMap directive.
– https://httpd.apache.org/docs/current/rewrite/rewritemap.html#dbm
This command may be introduced into build logic, allowing the created dbm
file(s) to be created automatically whenever content changes.