|
| 1 | +# Diagrams: API Basics |
| 2 | + |
| 3 | +[Back to concept](../api-basics.md) |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## REST API Architecture |
| 8 | + |
| 9 | +A REST API sits between the client and the database. It receives HTTP requests, processes them, and returns JSON responses. |
| 10 | + |
| 11 | +```mermaid |
| 12 | +flowchart LR |
| 13 | + subgraph CLIENTS ["Clients"] |
| 14 | + PY["Python script<br/>requests.get()"] |
| 15 | + WEB["Web browser<br/>fetch()"] |
| 16 | + MOB["Mobile app<br/>HTTP client"] |
| 17 | + end |
| 18 | +
|
| 19 | + subgraph API ["REST API Server"] |
| 20 | + ROUTER["Router<br/>Match URL to handler"] |
| 21 | + AUTH["Auth middleware<br/>Verify token/key"] |
| 22 | + HANDLER["Route handler<br/>Business logic"] |
| 23 | + SERIAL["Serializer<br/>Dict to JSON"] |
| 24 | + end |
| 25 | +
|
| 26 | + subgraph DATA ["Data Layer"] |
| 27 | + DB[("Database<br/>PostgreSQL")] |
| 28 | + CACHE[("Cache<br/>Redis")] |
| 29 | + end |
| 30 | +
|
| 31 | + PY -->|"HTTP request"| ROUTER |
| 32 | + WEB -->|"HTTP request"| ROUTER |
| 33 | + MOB -->|"HTTP request"| ROUTER |
| 34 | +
|
| 35 | + ROUTER --> AUTH |
| 36 | + AUTH --> HANDLER |
| 37 | + HANDLER --> DB |
| 38 | + HANDLER --> CACHE |
| 39 | + DB --> SERIAL |
| 40 | + SERIAL -->|"JSON response"| PY |
| 41 | + SERIAL -->|"JSON response"| WEB |
| 42 | + SERIAL -->|"JSON response"| MOB |
| 43 | +
|
| 44 | + style CLIENTS fill:#4a9eff,stroke:#2670c2,color:#fff |
| 45 | + style API fill:#cc5de8,stroke:#9c36b5,color:#fff |
| 46 | + style DATA fill:#51cf66,stroke:#27ae60,color:#fff |
| 47 | +``` |
| 48 | + |
| 49 | +## CRUD to HTTP Method Mapping |
| 50 | + |
| 51 | +REST maps the four database operations (Create, Read, Update, Delete) to HTTP methods and URL patterns. |
| 52 | + |
| 53 | +```mermaid |
| 54 | +flowchart TD |
| 55 | + subgraph CRUD ["Database Operation"] |
| 56 | + CREATE["CREATE<br/>Insert new row"] |
| 57 | + READ["READ<br/>Select rows"] |
| 58 | + UPDATE["UPDATE<br/>Modify row"] |
| 59 | + DELOP["DELETE<br/>Remove row"] |
| 60 | + end |
| 61 | +
|
| 62 | + subgraph HTTP ["HTTP Method + URL"] |
| 63 | + POST["POST /users<br/>Body: {name, email}"] |
| 64 | + GET1["GET /users<br/>List all"] |
| 65 | + GET2["GET /users/42<br/>Get one"] |
| 66 | + PUT["PUT /users/42<br/>Body: {name, email}"] |
| 67 | + DEL["DELETE /users/42<br/>No body"] |
| 68 | + end |
| 69 | +
|
| 70 | + subgraph RESPONSE ["Response"] |
| 71 | + R201["201 Created<br/>{id: 43, name: ...}"] |
| 72 | + R200L["200 OK<br/>[{id: 1}, {id: 2}, ...]"] |
| 73 | + R200O["200 OK<br/>{id: 42, name: ...}"] |
| 74 | + R200U["200 OK<br/>{id: 42, name: ...}"] |
| 75 | + R204["204 No Content"] |
| 76 | + end |
| 77 | +
|
| 78 | + CREATE --> POST --> R201 |
| 79 | + READ --> GET1 --> R200L |
| 80 | + READ --> GET2 --> R200O |
| 81 | + UPDATE --> PUT --> R200U |
| 82 | + DELOP --> DEL --> R204 |
| 83 | +
|
| 84 | + style CRUD fill:#ff922b,stroke:#e8590c,color:#fff |
| 85 | + style HTTP fill:#4a9eff,stroke:#2670c2,color:#fff |
| 86 | + style RESPONSE fill:#51cf66,stroke:#27ae60,color:#fff |
| 87 | +``` |
| 88 | + |
| 89 | +## API Request/Response Flow |
| 90 | + |
| 91 | +Step-by-step sequence of a typical API call from Python using the `requests` library. |
| 92 | + |
| 93 | +```mermaid |
| 94 | +sequenceDiagram |
| 95 | + participant Script as Python Script |
| 96 | + participant Lib as requests library |
| 97 | + participant API as API Server |
| 98 | + participant Logic as Route Handler |
| 99 | +
|
| 100 | + Script->>Lib: requests.post(url, json=data, headers=headers) |
| 101 | + Note over Lib: Serialize dict to JSON<br/>Add Content-Type header |
| 102 | +
|
| 103 | + Lib->>API: POST /users HTTP/1.1<br/>Authorization: Bearer eyJ...<br/>Content-Type: application/json<br/>{"name": "Alice", "email": "..."} |
| 104 | +
|
| 105 | + API->>API: Validate auth token |
| 106 | + API->>Logic: Call create_user handler |
| 107 | +
|
| 108 | + Note over Logic: Validate input<br/>Insert into database<br/>Build response |
| 109 | +
|
| 110 | + Logic-->>API: {"id": 43, "name": "Alice"} |
| 111 | + API-->>Lib: HTTP/1.1 201 Created<br/>Content-Type: application/json |
| 112 | +
|
| 113 | + Lib-->>Script: Response object |
| 114 | +
|
| 115 | + Note over Script: response.status_code → 201<br/>response.json() → {"id": 43, ...} |
| 116 | +``` |
| 117 | + |
| 118 | +## Authentication Token Flow |
| 119 | + |
| 120 | +How bearer token authentication works: login once, then include the token with every request. |
| 121 | + |
| 122 | +```mermaid |
| 123 | +sequenceDiagram |
| 124 | + participant Client as Python Client |
| 125 | + participant API as API Server |
| 126 | + participant DB as User Database |
| 127 | +
|
| 128 | + Note over Client: Step 1: Login to get a token |
| 129 | +
|
| 130 | + Client->>API: POST /auth/login<br/>{"username": "alice", "password": "s3cret"} |
| 131 | + API->>DB: Verify credentials |
| 132 | + DB-->>API: User found, password matches |
| 133 | +
|
| 134 | + Note over API: Generate JWT token<br/>Encode user ID + expiry |
| 135 | +
|
| 136 | + API-->>Client: 200 OK<br/>{"token": "eyJhbGci...", "expires_in": 3600} |
| 137 | +
|
| 138 | + Note over Client: Save the token |
| 139 | +
|
| 140 | + Note over Client: Step 2: Use token for API calls |
| 141 | +
|
| 142 | + Client->>API: GET /users/me<br/>Authorization: Bearer eyJhbGci... |
| 143 | +
|
| 144 | + Note over API: Decode token<br/>Verify signature<br/>Check expiry |
| 145 | +
|
| 146 | + API-->>Client: 200 OK<br/>{"id": 1, "name": "Alice", "role": "admin"} |
| 147 | +
|
| 148 | + Note over Client: Step 3: Token expires |
| 149 | +
|
| 150 | + Client->>API: GET /users/me<br/>Authorization: Bearer eyJhbGci... |
| 151 | +
|
| 152 | + Note over API: Token expired! |
| 153 | +
|
| 154 | + API-->>Client: 401 Unauthorized<br/>{"detail": "Token expired"} |
| 155 | +
|
| 156 | + Note over Client: Must login again<br/>to get a new token |
| 157 | +``` |
0 commit comments