Addresses that name things, methods that act
REST (Representational State Transfer) is a way to design a web API. Every address names a thing, and every method says what to do with it.
A well designed API is guessable. If you know /books lists the books, you can guess how to add one, change one and remove one.
By the end of this lesson
Note
I can design resource addresses and pick the right method for each job.
Key words
| Word | What it means | Example |
|---|---|---|
| Resource | a thing an API keeps, such as one book | |
| Collection | a list of resources of one kind | /books |
| Endpoint | the address of a resource or a collection | /books/7 |
| Idempotent | sending it twice leaves the same result as once | |
| Query string | the part of an address after ? that narrows a list | ?year=2004 |
The cells students fill in are left blank in this preview.
An address names a thing, never an action
A REST address is a noun. The resource is the thing, and the method is the verb. So /books is the collection of books and /books/7 is book number 7.
Do not put the action in the address. /getBooks and /deleteBook?id=7 repeat what the method already says. Use the plural for a collection, and nest a thing that belongs to another: /books/7/loans.
Worked example: weak addresses and better ones
| Weak address | Problem | Better address |
|---|---|---|
| /getBooks | The verb is in the address | GET /books |
| /book/7/delete | The action is in the address | DELETE /books/7 |
| /Books_List | Odd capitals and a made-up name | /books |
| /loans?book=7 | Fine for a filter, weak for ownership | /books/7/loans |
The cells students fill in are left blank in this preview.
Each method has one job
GET reads. POST adds a new resource and the server picks its id. PUT replaces a whole resource at a known address. PATCH changes some fields. DELETE removes.
A method is idempotent if sending it twice leaves the same result as sending it once. Idempotence matters because a network can fail after the server acted, so a client must know which requests are safe to repeat.
Worked example: the five methods compared
| Method | Job | Changes data | Idempotent |
|---|---|---|---|
| GET | Read | No | Yes |
| POST | Add a new one | Yes | No: twice makes two |
| PUT | Replace the whole thing | Yes | Yes |
| PATCH | Change some fields | Yes | Usually, when it sets a value |
| DELETE | Remove | Yes | Yes |
The cells students fill in are left blank in this preview.
Try the methods on a small catalogue
This lab's API is PostgREST. It names one row with a filter, so book 1 is /books?id=eq.1 where a classic REST API writes /books/1. The ideas are the same.
Run the next two commands to make a books table with three rows. Then each Run prints only the status code.
Give psql the password
export PGPASSWORD=shopShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Make the books table
psql -h db -U shop -c "drop table if exists books; create table books (id serial primary key, title text not null, year int not null, available boolean not null default true); insert into books (title, year, available) values ('Maps of the Sea', 1998, true), ('Rivers of Europe', 2004, false), ('Night Trains', 2011, true); notify pgrst, 'reload schema'"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
POST adds a book
curl -s -o /dev/null -w "%{http_code}\n" -X POST -H "Content-Type: application/json" -d '{"title":"Tide Tables","year":2019}' "http://api:3000/books"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
PATCH marks book 1 as out
curl -s -o /dev/null -w "%{http_code}\n" -X PATCH -H "Content-Type: application/json" -d '{"available":false}' "http://api:3000/books?id=eq.1"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Send the same PATCH again
curl -s -o /dev/null -w "%{http_code}\n" -X PATCH -H "Content-Type: application/json" -d '{"available":false}' "http://api:3000/books?id=eq.1"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think POST and PUT do the same job because both send data. They do not. POST adds a new resource and the server chooses its id, so repeating it makes a second one. PUT puts a whole resource at an address you name, so repeating it changes nothing.
A query string narrows a collection
Filtering, sorting and paging are not new resources. They narrow a collection, so they go in the query string: the part after the ?.
Write /books?year=2004 and not /books/2004, which looks like one book. In this lab the same idea is ?available=eq.true, and & joins two conditions.
Titles of the books on the shelf
curl -s -w "\n" "http://api:3000/books?available=eq.true&select=title&order=id"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.