Chapter 2
Write Requests by Hand
Safe and Idempotent Methods
In Chapter 1 you sent two kinds of request to practice-api: GET, which asks for a resource, and HEAD, which asks for the same response without its body. The first word of the request line is the
GET and HEAD. Three more matter for this course: POST, PUT, and DELETE. practice-api accepts only GET and HEAD, so you will not send the others to it; the server you write in Chapter 5 accepts all five.
Every method makes two promises a client can rely on. Both are about what happens to the data on the server, not about the reply that comes back.
Safe
A method is safe when the client asks for no change. Reading a book’s record changes nothing on the server, so GET is safe, and so is HEAD. A server may still write a line to its log or count the visit; safe means the client did not ask for a change and cannot be held responsible for one.
Idempotent
A method is
Take a reading DELETE /books/7 removes book 7. Send it again and book 7 is still gone; nothing else changed. So DELETE is idempotent, although it is not safe: the first request did change the list.
PUT /books/7 with a body sets book 7 to exactly that body. Send it twice and book 7 holds the same body either way, so PUT is idempotent too.
POST /books with a body asks the server to add a book and pick its number. Send it twice and the list holds two new books. POST is neither safe nor idempotent.
The five methods
| Method | Example on a reading list | Safe | Idempotent |
|---|---|---|---|
GET | GET /books/7: send book 7 | yes | yes |
HEAD | HEAD /books/7: send the head GET would send, without the body | yes | yes |
POST | POST /books: add this book and pick its number | no | no |
PUT | PUT /books/7: make book 7 exactly this | no | yes |
DELETE | DELETE /books/7: remove book 7 | no | yes |
Every safe method is also idempotent: a request that changes nothing leaves the same state however often you send it. The reverse is not true, as PUT and DELETE show.
Why a client cares
Sometimes a client sends a request and the reply never comes. The connection breaks, or the client’s timeout runs out. The client cannot tell whether the server never got the request, or got it, acted on it, and lost the reply on the way back.
For a GET, that question does not matter: send it again, and at worst the server reads the same book twice. For a PUT or a DELETE it does not matter either, because a second copy leaves the same state as the first. For a POST it matters a great deal: if the first request did arrive, sending it again adds the book a second time. So a client may repeat a safe or idempotent request after a lost reply, and must not repeat a POST without some other way of knowing whether the first one arrived. Chapter 5 comes back to this: your own server accepts POST and PUT there, and your tests show that repeating a POST adds a second book while repeating a PUT changes nothing more.
A client sends DELETE /books/7 twice. The first reply says it worked and has nothing to send back (204 No Content); the second says there is no such book (404 Not Found). Is DELETE idempotent here?
Choosing a method
The table also works the other way round: start from what you want done, and pick the method whose promises fit. Reading something is GET, or HEAD when the head is enough. Replacing something at a URL you already know is PUT. Removing it is DELETE. Adding something new whose URL the server decides is POST.
Which method fits "add a new book to the list; the server picks its number"?
The method is the first word of the request line. The second word is the target, which so far you have typed by hand. The next lesson takes a whole URL apart and shows where each of its parts goes.