First API
In this tutorial you will build three routes:
| Route | What it shows |
|---|---|
GET /hello | Plain text responses. |
GET /users/:id | Path parameters and JSON responses. |
POST /echo | JSON request bodies and custom status codes. |
Start with:
flint new my-api
cd my-api
flint serveOpen the routes/ directory in another terminal or editor.
How Route Files Work
The server loads every .fl file directly inside routes/:
routes/
├── hello.fl
├── users.fl
└── echo.flEach file may define functions and route declarations. A route declaration maps an HTTP method and path to a function:
route GET "/hello" -> say_helloRoute 1: Plain Text
Create or replace routes/hello.fl:
say_hello:
mov r0, "Hello from Flint!"
ncall http.text, r0
ret
route GET "/hello" -> say_helloTest it:
curl http://127.0.0.1:3000/helloExpected response:
Hello from Flint!The request flow:
- The router matches
GET /hello. - The runtime creates a fresh VM.
- The VM calls
say_hello. http.textsets the response body.retreturns to the HTTP runtime.
Route 2: Path Params and JSON
Create routes/users.fl:
show_user:
mov r0, "id"
ncallr r1, http.param, r0
ncallr r2, json.object
mov r3, "id"
ncallr r2, json.set, r2, r3, r1
mov r3, "source"
mov r4, "Flint"
ncallr r2, json.set, r2, r3, r4
ncall http.json, r2
ret
route GET "/users/:id" -> show_userTest it:
curl http://127.0.0.1:3000/users/42Expected response:
{"id":"42","source":"Flint"}The key pattern is:
mov r0, "id"
ncallr r1, http.param, r0http.param receives the parameter name and returns the value captured from the path.
Building JSON
There is no JSON literal syntax. Build JSON values with native functions:
| Goal | Call |
|---|---|
| Empty object | ncallr r0, json.object |
| Empty array | ncallr r0, json.array |
| Set object field | ncallr r0, json.set, r0, key, value |
| Push array item | ncallr r0, json.push, r0, value |
json.set and json.push return new JSON documents. Store the result:
ncallr r0, json.object
mov r1, "name"
mov r2, "Ada"
ncallr r0, json.set, r0, r1, r2Route 3: Read a POST Body
Create routes/echo.fl:
echo_body:
ncallr r0, http.json_body
ncallr r1, json.object
mov r2, "received"
ncallr r1, json.set, r1, r2, r0
mov r2, 201
ncall http.set_status, r2
ncall http.json, r1
ret
route POST "/echo" -> echo_bodyTest it:
curl -i -X POST http://127.0.0.1:3000/echo \
-H 'Content-Type: application/json' \
-d '{"name":"Ada"}'Expected body:
{"received":{"name":"Ada"}}http.json_body parses the request body as JSON. Invalid JSON becomes a runtime error and the HTTP runtime returns 500.
Change the Status Code
Every response starts as 200 OK. Set another status with:
mov r0, 201
ncall http.set_status, r0The response is sent after the handler returns, so the status can be set before or after the body.
Try Everything
curl http://127.0.0.1:3000/hello
curl http://127.0.0.1:3000/users/42
curl -i -X POST http://127.0.0.1:3000/echo \
-H 'Content-Type: application/json' \
-d '{"x":1}'
curl -i http://127.0.0.1:3000/missingNext: Visual Pages.