|
| 1 | +-- This migration documents the JSON/JSONL response format feature based on HTTP Accept headers |
| 2 | + |
| 3 | +-- Update the json component description to include information about the Accept header feature |
| 4 | +UPDATE component |
| 5 | +SET description = 'Converts SQL query results into the JSON machine-readable data format. Ideal to quickly build APIs for interfacing with external systems. |
| 6 | + |
| 7 | +**JSON** is a widely used data format for programmatic data exchange. |
| 8 | +For example, you can use it to integrate with web services written in different languages, |
| 9 | +with mobile or desktop apps, or with [custom client-side components](/custom_components.sql) inside your SQLPage app. |
| 10 | +
|
| 11 | +Use it when your application needs to expose data to external systems. |
| 12 | +If you only need to render standard web pages, |
| 13 | +and do not need other software to access your data, |
| 14 | +you can ignore this component. |
| 15 | +
|
| 16 | +This component **must appear at the top of your SQL file**, before any other data has been sent to the browser. |
| 17 | +An HTTP response can have only a single datatype, and it must be declared in the headers. |
| 18 | +So if you have already called the `shell` component, or another traditional HTML component, |
| 19 | +you cannot use this component in the same file. |
| 20 | +
|
| 21 | +### Alternative: Using HTTP Accept Headers |
| 22 | +
|
| 23 | +SQLPage also supports returning JSON or JSON Lines responses based on the HTTP `Accept` header, |
| 24 | +without needing to use this component. This is useful when you want the same SQL file to serve |
| 25 | +both HTML pages (for browsers) and JSON data (for API clients). |
| 26 | +
|
| 27 | +See [Automatic JSON output based on Accept headers](#example4) for more details. |
| 28 | +' |
| 29 | +WHERE name = 'json'; |
| 30 | + |
| 31 | +-- Add a new example for the Accept header feature |
| 32 | +INSERT INTO example (component, description) |
| 33 | +VALUES ( |
| 34 | + 'json', |
| 35 | + ' |
| 36 | +## Automatic JSON output based on HTTP Accept headers |
| 37 | +
|
| 38 | +SQLPage can automatically return JSON or JSON Lines responses instead of HTML based on the HTTP `Accept` header sent by the client. |
| 39 | +This allows the same SQL file to serve both web browsers and API clients. |
| 40 | +
|
| 41 | +### How it works |
| 42 | +
|
| 43 | +When a client sends a request with an `Accept` header, SQLPage checks if the client prefers JSON: |
| 44 | +
|
| 45 | +- `Accept: application/json` → Returns a JSON array of all component data |
| 46 | +- `Accept: application/x-ndjson` → Returns JSON Lines (one JSON object per line) |
| 47 | +- `Accept: text/html` or `Accept: */*` → Returns the normal HTML page |
| 48 | +
|
| 49 | +All other SQLPage features work exactly the same: |
| 50 | +- Header components (`redirect`, `cookie`, `http_header`, `status_code`, `authentication`) work as expected |
| 51 | +- SQLPage functions and variables work normally |
| 52 | +- The response just skips HTML template rendering |
| 53 | +
|
| 54 | +### Example: A dual-purpose page |
| 55 | +
|
| 56 | +The following SQL file works as both a normal web page and a JSON API: |
| 57 | +
|
| 58 | +```sql |
| 59 | +-- Header components work with both HTML and JSON responses |
| 60 | +SELECT ''cookie'' AS component, ''last_visit'' AS name, datetime() AS value; |
| 61 | +SELECT ''status_code'' AS component, 200 AS status; |
| 62 | +
|
| 63 | +-- These will be rendered as HTML for browsers, or returned as JSON for API clients |
| 64 | +SELECT ''text'' AS component, ''Welcome!'' AS contents; |
| 65 | +SELECT ''table'' AS component; |
| 66 | +SELECT id, name, email FROM users; |
| 67 | +``` |
| 68 | +
|
| 69 | +### HTML Response (default, for browsers) |
| 70 | +
|
| 71 | +```html |
| 72 | +<!DOCTYPE html> |
| 73 | +<html> |
| 74 | + <!-- Normal SQLPage HTML output --> |
| 75 | +</html> |
| 76 | +``` |
| 77 | +
|
| 78 | +### JSON Response (when Accept: application/json) |
| 79 | +
|
| 80 | +```json |
| 81 | +[ |
| 82 | + {"component":"text","contents":"Welcome!"}, |
| 83 | + {"component":"table"}, |
| 84 | + {"id":1,"name":"Alice","email":"[email protected]"}, |
| 85 | + {"id":2,"name":"Bob","email":"[email protected]"} |
| 86 | +] |
| 87 | +``` |
| 88 | +
|
| 89 | +### JSON Lines Response (when Accept: application/x-ndjson) |
| 90 | +
|
| 91 | +``` |
| 92 | +{"component":"text","contents":"Welcome!"} |
| 93 | +{"component":"table"} |
| 94 | +{"id":1,"name":"Alice","email":"[email protected]"} |
| 95 | +{"id":2,"name":"Bob","email":"[email protected]"} |
| 96 | +``` |
| 97 | +
|
| 98 | +### Using from JavaScript |
| 99 | +
|
| 100 | +```javascript |
| 101 | +// Fetch JSON from any SQLPage endpoint |
| 102 | +const response = await fetch("/users.sql", { |
| 103 | + headers: { "Accept": "application/json" } |
| 104 | +}); |
| 105 | +const data = await response.json(); |
| 106 | +console.log(data); |
| 107 | +``` |
| 108 | +
|
| 109 | +### Using from curl |
| 110 | +
|
| 111 | +```bash |
| 112 | +# Get JSON output |
| 113 | +curl -H "Accept: application/json" http://localhost:8080/users.sql |
| 114 | +
|
| 115 | +# Get JSON Lines output |
| 116 | +curl -H "Accept: application/x-ndjson" http://localhost:8080/users.sql |
| 117 | +``` |
| 118 | +
|
| 119 | +### Comparison with the json component |
| 120 | +
|
| 121 | +| Feature | `json` component | Accept header | |
| 122 | +|---------|------------------|---------------| |
| 123 | +| Use case | Dedicated API endpoint | Dual-purpose page | |
| 124 | +| HTML output | Not possible | Default behavior | |
| 125 | +| Custom JSON structure | Yes (via `contents`) | No (component data only) | |
| 126 | +| Server-sent events | Yes (`type: sse`) | No | |
| 127 | +| Requires code changes | Yes | No | |
| 128 | +' |
| 129 | +); |
| 130 | + |
0 commit comments