Hugo respects _redirects files: desirable feature?

Netlify, Cloudflare and IPFS allow use of a _redirects file to direct their HTTP servers to send specific HTTP status codes and Location headers for paths that don’t exist in the static files they serve.

I’d like to see Hugo’s local dev server respect these files, so as to better test how my sites will work when published. I’m willing to build/submit a PR for this feature, if it seems desirable, and the Hugo team deem it suitable of maintenance costs. Is this interesting to you?

A sample file:

# Hash-starting lines are comments, empty lines are ignored

/blog/:name /posts/:name 307
/posts/example-product-launch/ 308
* /404.html 404

Instructions are processed top to bottom; this file will:

  1. Serve existing files without checking this file
  2. Compare the inbound URL against /blog/<anything>, if it matches it will send an HTTP 307 response code with Location: /posts/<anything> (replacing <anything> with whatever matched)
  3. Only if the previous rule(s) didn’t match, it’ll check the inbound URL against /posts/example-product-launch/, and send an HTTP 308 redirect with Location: if it matches.
  4. Only if the previous rule(s) didn’t match, it’ll return the contents of 404.html with an HTTP 404 response code.

This appears simple, but there are plenty of edge-cases. There is MIT licensed Go code for processing this file in IPFS’ go-ipfs-redirects-file repo that I’d use/reuse.

Some open thoughts & questions:

  • I’d expect this to be an opt-in feature, so Hugo users have opportunity to understand that the functionality comes from their hosting provider (Cloudflare, Netlify, IPFS) and not with other hosts.
  • Though these providers allow a _redirects file to be in any directory, I believe it’d be reasonable for Hugo to constrain this file to only living at the root (ie. stored at static/_redirects before build)

I did not test, but I think this should meet your need.

and this too I think


Nice! I’m sure I can whip up a tool that ensures my _redirects file is correctly converted into Hugo-specific TOML.

Thanks folks!

There are three cases to consider:

  1. Manually create redirect entries
  2. Automatically create redirect entries
  3. A combination of the above

With respect to #2, this is a common approach to automatically create a _redirects file from the aliases as defined in front matter:

{{ if .IsHome }}
  {{ $s := "" }}
  {{ range $p := site.Pages }}
    {{ range .Aliases }}
      {{ $s = printf "%s%s %s 301\n" $s . $p.RelPermalink }}
    {{ end }}
  {{ end }}
  {{ (resources.FromString "_redirects" $s).Publish }}
{{ end }}

The above writes something like this to public/_redirects:

/baz /posts/post-2/ 301
/foo /posts/post-1/ 301
/bar /posts/post-1/ 301

In this situation, there is no need for Hugo’s development server to read the _redirects file because the browser redirection is already handled by the alias files created in the development environment.

So this proposed feature is only required to handle case #1 and case #3 as defined above: manual creation of redirect entries. I don’t think this is terribly common, so I’m not convinced there’s a great ROI here.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.