How to handle redirects directly in your Sphinx project

Dmitri Popov

When you use Sphinx to document your software, you sometimes move files to a different location as part of a content refactoring. Then, you need to set up redirects that point from the old to the new location of a content piece.

If you make your documentation available on one particular domain, the obvious way to handle redirects is to ask the system administrator to configure the redirects on web server side, for example in Apache .htaccess files. But in case you release the docs on multiple platforms or even have them deployed locally within a customer’s internal network, you can reduce the organizational overhead by managing the redirects yourself, directly within your Sphinx project. This blog post explains how.

Redirect template

First you need to create an HTML template for redirect handling. It triggers the redirect via an HTML meta tag and also via JavaScript (to support some possible edge cases). You find alternative approaches on Stack Overflow. In this example, <./new_url> is the placeholder for the actual target URL that points to the new location of the file:

<html>
  <head>
    <meta http-equiv="refresh" content="1; url=<./new_url>:" />
    <script>
      window.location.href = "<./new_url>"
    </script>
  </head>
</html>

Every time you make a refactoring that moves an entire file, place the HTML file with the template snippet to the folder you moved the source file from and adjust the redirect target ( <./new_url>). Of course, the HTML file needs to have the same name as the compiled moved file. For example, if your source file was folders.rst, name the output file folders.html.

Setup script in project configuration file

By default, Sphinx won’t process the redirect files (it only considers source files). That’s why you need to write a couple of lines of Python code to copy the redirect files to their correct place in the build directory. You can simply add the lines to your project’s conf.py configuration file.

Create a list that contains all redirect files:

redirect_files = ['explorer/basics/deleting_and_restoring.html']

Alternatively, you could write a script that collects all paths to HTML files in your source directory.

Now, define a function that copies all redirect files from the source directory to the equivalent position in the output directory. For this, you can conveniently make use of Sphinx’s application API:

from shutil import copyfile
# copy legacy redirects
def copy_legacy_redirects(app, docname): # Sphinx expects two arguments
    if app.builder.name == 'html':
        for html_src_path in redirect_files:
            target_path = app.outdir + '/' + html_src_path
            src_path = app.srcdir + '/' + html_src_path
        if os.path.isfile(src_path):
            copyfile(src_path, target_path)

Finally, register the function on the build-finished Sphinx core event to execute the function when the Sphinx build finishes:

def setup(app):
    app.connect('build-finished', copy_legacy_redirects)

That’s all! After you run your Sphinx build command, the tool will include the HTML redirect files at the desired location in the build folder.