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.