Your first app¶
Make a project, write a server that answers one request, and run it. This assumes Spindle is installed.
1. Make the project¶
A project is a folder with three files:
dune-project marks the folder as a dune project:
bin/dune builds a program named main that uses Spindle and Eio’s event
loop. The preprocess line lets [@@deriving wiretype] write a JSON
description of each of your types, which the tutorial uses from the next
page on:
bin/main.ml is the server:
let good_morning = Ok "Good morning, world!"
let routes =
[
Spindle.get Spindle.Path.root Spindle.Returns.text
(Spindle.Dep.return good_morning);
]
let () = Eio_main.run @@ fun env -> Spindle.serve env routes
2. Run it¶
From the hello folder:
dune exec compiles, reports any mistake with its file and line, and runs.
Open http://localhost:8080, or from another terminal:
Ctrl-C stops the server.
Rebuilding as you type
dune build --watch in a terminal of its own compiles on every save.
3. What the code says¶
- The answer,
good_morning, isOkof the text to send. AnErrorwould refuse the request instead. - The routes are a list.
Spindle.getis the method,Spindle.Path.rootthe path/, andSpindle.Returns.textsays it answers text. The last argument says what the route reads from the request and how it works out its answer. This route reads nothing and always gives the same answer, so it isSpindle.Dep.return good_morning. The next page shows routes that read their inputs. - The server:
Eio_main.runstarts the event loop, andSpindle.serveserves the routes until you stop it.
4. Turn on the log¶
Add one line to see every request:
Every request is now a line with its method, path, status, duration (in nanoseconds) and an id:
10:11:03.331 info spindle.http [cm5nxptpka21] GET / 200 http.request.method=GET url.path=/ http.response.status_code=200 duration=14875 http.response.body.size=20 http.route=/
Lines look like this in a terminal. When stderr is not a terminal – a container, a file, a log collector – each line is JSON instead.
The same id is in the answer’s x-request-id header, so a request a user
reports can be found in the log. More in logging.
What you get for free¶
Ask for something the server does not do:
HTTP/1.1 405 Method Not Allowed
content-type: application/json
allow: GET, HEAD, OPTIONS
...
{"error":"method_not_allowed","message":"That is not something you can do here."}
- Every error in one JSON shape: a code a program can check and a sentence a person can read. Internal errors go to the log, never to the client.
- Every CPU core serving, from the first request.
- A clean stop on
Ctrl-C, letting requests in flight finish.
Another port is one argument: Spindle.serve env ~port:3000 routes.
Next: routes.