Skip to main content

Say What You Mean

A REST API talks through two vocabularies. The method says what the client wants: GET read, POST create, PUT replace, PATCH change a part, DELETE remove. The status code says how it went: 2xx success, 4xx the client's mistake, 5xx the server's.

A detail worth knowing: PUT is idempotent — sending it twice ends the same as once. POST is not: two POSTs create two resources.


The Right Method

The router matches the method as well as the path, so every verb gets its own handler. Creation answers 201 Created and points at the new resource with a Location header; deletion answers 204 No Content — success with nothing to say, so the body stays empty.

GET, POST and DELETE on one resource

Three verbs, three answers: the list comes back with 200, the creation with 201 and a Location, the deletion with 204 and an empty body.

Prompt
Write a TypeScript program with a small method-aware router handling GET /notes (200 with a list line), POST /notes (201 with a Location header) and DELETE /notes/{id} (204, empty body). Serve it on port 0, send the three requests with fetch and print each method, status code and any Location header or body.
Output: TypeScript file and captured output

The Right Status Code

Errors deserve precision too: a missing resource is 404 Not Found, with a JSON error body so machines can read it. A wrong verb on a known path is 405 Method Not Allowed.

Nothing sends that 405 for you here. The router checks both parts separately: if some route's path matched but no route's method did, it answers 405 and adds an Allow header listing the verbs that would have worked.

200, 404 and 405

The existing note returns 200 with data, the missing one 404 with a JSON error, and the DELETE on a GET-only route is refused with 405 by the router itself.

Prompt
Write a TypeScript program with a GET /notes/{id} handler that returns 200 with JSON for an existing note and 404 with a JSON error body for a missing one, and a router that answers 405 with an Allow header when the path matches but the method does not. Serve it on port 0, then request an existing note, a missing note and a DELETE on the same path, printing all three results.
Output: TypeScript file and captured output