0%

Chapter 6

Redirects

A Resource That Moved

The reading can now create, replace and delete books, and every path it answers is a current one: /books and /books/{id}. The first version of this API lived somewhere else, under /v0/books, and some old clients still call those paths. This chapter’s SERVICE_CONTRACT.md, which you will open in Lesson 3, has a new section, “Old paths”, that says what the server owes them.

There are two easy answers, and both are wrong. The server could answer /v0/books/2 with a 404, which breaks every old client the day the paths change. Or it could keep a second copy of every route under /v0, which works until someone fixes a bug in one copy and not the other, and the two versions start to disagree. has a third answer: a redirect. The server replies “this is somewhere else now, ask there”, and the client sends its request again to the new address. One copy of the code, and old clients keep working.

Where and how

A redirect is a with a location header. The two parts answer different questions:

  • location says where the resource is now, for example location: /books/2.

  • The status says how to go there: whether the move is permanent, and whether a client that follows it may change the .

Five statuses do this, and two questions sort them:

                 POST may become GET          method and body kept
permanent        301 Moved Permanently        308 Permanent Redirect
temporary        302 Found                    307 Temporary Redirect

303 See Other:   fetch the location with GET (or HEAD), whatever the method was

Read it as a grid. The rows say whether the move is permanent: 301 and 308 mean “use the new address from now on”, 302 and 307 mean “use it this time, and ask here again next time”. The columns say what happens to the method. After a 307 or 308 the client sends the same method with the same body to the new address, so a PUT stays a PUT. After a 301 or 302 a client may turn a POST into a GET and drop its body; every other method is kept. 303 stands apart: it means “now fetch this other address”, and RFC 9110 says that fetch is a GET or a HEAD. The follower you write in Lesson 4 sends GET, and Lesson 5 shows a library that keeps a HEAD a HEAD.

Browsers remember a permanent redirect and may go straight to the new address next time. That is a browser feature you will only recognize here; the clients in this course ask every time.

Why five and not two

Two would be enough on paper: one permanent, one temporary. HTTP/1.0 had two redirect codes, 301 and 302, and neither allowed a client to change the method on its own. Browsers changed it anyway: after a POST answered with 301 or 302, most of them sent a GET to the new address and dropped the body, and enough servers came to rely on that behavior that it could no longer be called a mistake.

So HTTP added codes instead of changing old ones. 303 says outright what browsers were doing: fetch the result with a GET (or a HEAD). 307 and 308 say the opposite: keep the method and the body, whatever happens. RFC 9110 (section 15.4) still allows the old behavior for 301 and 302, and only for POST: a client may change a POST into a GET there, and keeps every other method. A server that needs a POST or a PUT to arrive unchanged sends 307 or 308, where no change is allowed at all.

That is why the reading list will use 308 for /v0/books: the move is permanent, and an old client’s PUT has to reach the new path as a PUT, with its body.

No location, no redirect

The status alone does not make a redirect. A 3xx that comes without a location header gives the client nowhere to go, so a client treats it as the final reply and hands it back. Not every 3xx is a redirect either: 304 Not Modified, which Chapter 8 builds, says “your cached copy is still good”, and it has no location.

Following a redirect is always the client’s decision. http.client, which you used in Chapter 3, makes no such decision: it sends one request and hands back one response. Asked for GET /v0/books/2?x=1 on a server that redirects it, it returns 308 Permanent Redirect with location: /books/2?x=1 and stops there. Lesson 4 writes the code that reads that header and sends the next request, and Lesson 5 compares it with a library that follows redirects for you.

/v0/books/{id} moved for good, and old clients send PUT there. Which status should the server send?

After a form POST, the server wants the client to load the result page with GET. Which status says that?

Book 7 is served from /books/7-old for an hour during maintenance, and PUT must keep working. Which status sends clients there?

The server will send location: /books/2, not a full , and that means nothing until the client works out which URL it stands for. The next lesson resolves a relative location against the URL that was requested.