Representational State Transfer
"URLs are nouns, HTTP methods are verbs. Resources are identified by URLs, manipulated via HTTP methods, and transferred as representations — usually JSON."
CSE 135 — Full Overview | Review Questions
Mapping data operations to HTTP methods and URL patterns.
| CRUD | HTTP Method | Collection URL | Item URL |
|---|---|---|---|
| Create | POST | /api/books | — |
| Read | GET | /api/books | /api/books/42 |
| Update | PUT / PATCH | — | /api/books/42 |
| Delete | DELETE | — | /api/books/42 |
The RESTful spectrum — from good to bad.
| URL | RESTfulness | Why |
|---|---|---|
GET /api/books/1 | RESTful | Resource in URL, method implies action |
GET /api/books?id=1 | Less RESTful | Works, but ID should be in the path |
GET /api?record=books&id=1 | Not RESTful | Resource type hidden in query params |
GET /api?id=1&action=delete | Definitely not REST | Action in URL, wrong HTTP method |
/api/getBooks, you're putting the verb in the URL instead of using HTTP methods. The whole point of REST is that the HTTP method is the verb.
Communicate results through standard codes, not ad-hoc JSON.
| Code | When |
|---|---|
200 OK | GET, PUT, PATCH, DELETE success |
201 Created | POST created a resource |
204 No Content | DELETE with no body |
| Code | When |
|---|---|
400 | Malformed / invalid input |
401 | Not authenticated |
403 | Authenticated, wrong permissions |
404 | Resource doesn't exist |
409 | Conflict (duplicate) |
422 | Valid JSON, invalid semantics |
| Operation | Success | Errors |
|---|---|---|
| POST | 201 | 400, 409 |
| GET | 200 | 404 |
| PUT | 200 | 404, 400 |
| DELETE | 200/204 | 404 |
| Code | When |
|---|---|
500 | Bug, DB down, unhandled error |
Full replacement vs partial update — and idempotency.
| Aspect | PUT | PATCH |
|---|---|---|
| Semantics | Full replacement — send entire resource | Partial update — send only changed fields |
| Missing fields | Set to defaults or removed | Left unchanged |
| Idempotent? | Yes — same PUT twice = same result | Not guaranteed |
| Example | PUT /api/books/42{"title":"New","author":"X","year":2024} | PATCH /api/books/42{"year":2025} |
REST is format-agnostic — JSON dominates, but it's not the only option.
| Content-Type | When Used |
|---|---|
application/json | JavaScript clients, API-to-API calls |
application/x-www-form-urlencoded | Standard HTML form submissions |
multipart/form-data | File uploads and mixed data |
| Language | Encode | Decode |
|---|---|---|
| JavaScript | JSON.stringify(obj) | JSON.parse(str) |
| PHP | json_encode($arr) | json_decode($str, true) |
Accept and Content-Type headers enable format negotiation for HTML, CSV, XML, and more.
| Accept Header | Use Case |
|---|---|
application/json | JavaScript clients, SPAs, mobile apps |
text/html | Server-side rendering, HTMX, progressive enhancement |
text/csv | Data exports, spreadsheets |
application/xml | Legacy systems, enterprise, RSS/Atom |
application/pdf | Generated reports, invoices |
Four levels of REST maturity — and why most stop at Level 2.
Design considerations change based on who consumes your API.
| Aspect | Private API | Public API |
|---|---|---|
| Consumers | Your own front-end team | External developers worldwide |
| Breaking changes | Coordinate & deploy together | Can't — people depend on old behavior |
| Versioning | Often unnecessary | Essential: /v1/api/books |
| Documentation | Team Wiki, Slack | Published docs, OpenAPI spec |
| HATEOAS | Rarely needed | Valuable for discoverability |
| Strategy | Example | Notes |
|---|---|---|
| URL path (most common) | GET /v1/api/books | Most visible, widely used |
| Header | Accept: application/vnd.myapi.v2+json | Cleaner URLs, harder to test |
| Query parameter | GET /api/books?version=2 | Easy to add, less standard |
Real-world complications with PUT, DELETE, and form submissions.
| Problem | Solution |
|---|---|
| Corporate proxy strips PUT/DELETE | Use HTTPS (proxy can't inspect encrypted traffic) |
| Firewall blocks methods | POST with X-HTTP-Method-Override: PUT header |
| HTML forms only support GET/POST | JavaScript fetch() or hidden field _method=PUT |
| CORS preflight overhead | Handle OPTIONS in your API |
Cross-Origin Resource Sharing — how browsers enforce access control.
Access-Control-Allow-* headers to tell the browser what's permitted. Using * for Allow-Origin is dangerous in production — specify exact trusted origins instead.
Mocking, specification, and documentation tools.
npx json-server db.json| Tool | Purpose |
|---|---|
| Swagger UI | Interactive HTML docs |
| Swagger Editor | Browser editor + validation |
| Codegen | Generate client SDKs / server stubs |
Same REST API, different implementation details.
| Concept | Node.js (Express) | PHP |
|---|---|---|
| Get HTTP method | req.method | $_SERVER['REQUEST_METHOD'] |
| URL parameter | req.params.id | $_SERVER['PATH_INFO'] + parsing |
| Read JSON body | req.body (middleware) | json_decode(file_get_contents('php://input'), true) |
| Send JSON | res.json(data) | echo json_encode($data) |
| Set status | res.status(201).json(data) | http_response_code(201) |
| Routing | app.get('/api/items/:id', ...) | Manual via PATH_INFO + switch |
| Data persistence | In-memory (process stays running) | File or DB (process restarts each request) |
| Execution model | Persistent process | Per-request |
APIs are contracts — testing verifies the contract holds.
| Tool | Type | Best For |
|---|---|---|
| curl | CLI | Universal, CI pipelines |
| HTTPie | CLI | Human-friendly syntax |
| Postman | GUI | Team collaboration |
| DevTools | Browser | Inspect live requests |
| supertest | Code | Automated testing (Node) |
When REST isn't enough — GraphQL, gRPC, and microservice pitfalls.
| Aspect | REST | GraphQL | gRPC |
|---|---|---|---|
| Data format | JSON (text) | JSON (text) | Protocol Buffers (binary) |
| Endpoints | Many (/users, /posts) | One (/graphql) | Per service/method |
| Best for | CRUD, public APIs, simple apps | Complex UIs, mobile apps | Service-to-service, streaming |
| HTTP caching | Works great (GET cacheable) | Custom caching needed | Not typically used |
| Browser support | Native (fetch, XHR) | Native (just POST) | Needs proxy (gRPC-Web) |
| Learning curve | Low | Medium | Higher |
| Debugging | Easy (curl, DevTools) | Moderate | Harder (binary) |
13 sections of REST API fundamentals in one table.
| Concept | Key Points |
|---|---|
| CRUD & REST | POST=Create, GET=Read, PUT/PATCH=Update, DELETE=Delete. Collection URL vs item URL. |
| URL Design | Nouns in URLs (/api/books/42), verbs in HTTP methods. Avoid /api/getBooks. |
| Status Codes | 200 OK, 201 Created, 204 No Content, 400/401/403/404 client errors, 500 server error. |
| PUT vs PATCH | PUT replaces entire resource; PATCH updates specific fields. PUT is idempotent. |
| Formats | REST is format-agnostic. JSON dominates, but Accept/Content-Type enable negotiation. |
| Maturity Model | Level 0 (one URL) → Level 1 (resources) → Level 2 (verbs) → Level 3 (HATEOAS). |
| Public vs Private | Public APIs need versioning, docs, stability. Design as if it might become public. |
| Method Challenges | Proxies, firewalls, forms limit HTTP methods. HTTPS and method override solve most issues. |
| CORS | Browser-enforced; server sends Access-Control-Allow-* headers. Don't use * in production. |
| Tooling | json-server for prototyping, OpenAPI/Swagger for specs and docs. |
| Node.js vs PHP | Same CRUD, different persistence: Node keeps state in memory, PHP needs external storage. |
| Testing | curl for CLI, Postman for GUI, supertest for automation. Test happy paths and error cases. |
| Beyond REST | GraphQL for flexible queries, gRPC for fast service-to-service. Start with REST. |