Skip to content

Redirects

Scope: sending visitors somewhere else — return for the simple cases, rewrite for pattern work, and the canonical-host shape you'll write a dozen times.

return is the blunt, honest tool

location /old-page { return 301 /hello.txt; }
$ curl -sI http://127.0.0.1:8080/old-page
HTTP/1.1 301 Moved Permanently
Server: nginx/1.24.0 (Ubuntu)
Date: Tue, 20 Oct 2026 20:45:31 GMT
Content-Type: text/html
Content-Length: 178
Location: http://127.0.0.1:8080/hello.txt

The status and the destination, nothing else. return takes a code and a body or URL: return 200, return 404, return 301 /elsewhere. For "this exact path now lives there," it is always the right answer — faster than rewrite, and readable in one line.

The stock uses: moved pages, trailing-slash normalisation, and whole-server moves:

server {
    listen 127.0.0.1:8082;
    server_name localhost;
    return 301 https://$host:8443$request_uri;
}
$ curl -sI http://127.0.0.1:8082/hello.txt
HTTP/1.1 301 Moved Permanently
Location: https://127.0.0.1:8443/hello.txt

$request_uri carries the path and query string along, so /anything?x=1 lands on the HTTPS equivalent intact. (This is the lab's HTTP→HTTPS server block, used again in chapter 9.)

rewrite is pattern work

When the destination depends on the shape of the incoming path, rewrite matches a regular expression:

location /blog/ { rewrite ^/blog/(.*)$ /articles/$1 permanent; }
$ curl -sI http://127.0.0.1:8080/blog/my-first-post
HTTP/1.1 301 Moved Permanently
Location: http://127.0.0.1:8080/articles/my-first-post

The flags: permanent means 301, redirect means 302, and no flag re-serves the request internally (the visitor never sees it move — that last form is the one that quietly powers pretty URLs).

301 versus 302, and the usual mistakes

  • 301 (permanent): browsers cache it, hard. Use it when the move is really forever. Move something back later and visitors keep landing on the old target until the cache dies — the classic "I fixed the redirect and it didn't fix" call is a cached 301.
  • 302 (temporary): not cached, the right default while you're unsure.

Two habits: prefer return whenever the destination is a fixed string (reach for rewrite only for patterns), and during any redirect work test with curl -I instead of a browser — browsers remember 301s, curl forgets them the moment you look away.

Check: pick one URL you actually want to move and write it both ways — return for the fixed form and a rewrite for the pattern form. If they differ, return was the wrong tool.