Micro Api
API Address: https://api.nkozak.com/
Routes: Start with just GETing the root, it provides instructions.
At the moment the welcome API route responds with:
Welcome! This is my little API.
It is written in Racket, and will continue to grow until the end of class.
=== MESSAGE BOARD ===
GET /message
Retrieve the current message from the "wall"
POST /message
Post a message to the wall
Body: {"name": "Your name", "message": "Something you feel like saying"}
=== DYNAMIC COLOR ===
GET /color
Returns current RGB color values that evolve smoothly over time
Response: {"r": 0-255, "g": 0-255, "b": 0-255, "rate": number}
POST /color
Influence the color evolution
Body (all optional):
{"rate": 0-10} - Speed of color changes (0=frozen, 10=fastest)
{"r": 0-255} - Target red value
{"g": 0-255} - Target green value
{"b": 0-255} - Target blue value
Example: {"rate": 2.5, "r": 255, "g": 0, "b": 128}
=== SYSTEM ===
GET /health
Health check endpoint
I spent the afternoon putting together the rudiments of a little servlet. At the moment it fulfills the use-case of the class exercise: an easy-to-use API that responds with some interesting data, that someone else in the class can pull. My idea is to eventually create a small game that teaches users how to best use curl. The game would progress from simple GET requests to sending multi-part forms and handling cookies, user-agents, etc. I have the basic “curriculum” laid out. The rules for endpoints would go something like:
Level 6: DELETE with headers
DELETE /level/6/{id} with header Confirm: yes
{
"success": true,
"lesson": "Headers carry metadata; DELETE removes resources",
"instruction": "Pretend to be a bot: GET /level/7 with custom User-Agent",
"required_header": "User-Agent: CurlBot/1.0",
"hint": "curl -H 'User-Agent: CurlBot/1.0' ..."
}
Where every reply gives you info on the next endpoint.
But, for now, I’ve just installed a basic server that serves as a message wall - you POST a message, and can GET the last posted message. Nothing fancy.
The server is written in Racket, which I’m trying to work with a bit more - other than for creating DSL’s, I never really dug too deap into its use as a general-purpose language. The nice things about lisps for dispatching (i.e. perfect for routing in a server) is how sane the language is:
; Dispatch-values
(define-values (servlet-dispatch servlet-url)
(dispatch-rules
[("message") #:method "get" get-message-endpoint]
[("message") #:method "post" post-message-endpoint]
[("health") #:method "get" health-endpoint]
[("") #:method "get" welcome-endpoint]
[else welcome-endpoint]))
Other affordances, like inline evaluation of JSON structs, is also nice:
(define (health-endpoint req)
(response/jsexpr
(hasheq 'status "healthy"
'timestamp (exact->inexact (current-seconds)))))
I deployed the server to my DigitalOcean VPS, provided it with a /health endpoint for monitoring, and set it up as a service using systemctl. This allows me to restart the server automatically if anything goes wrong. I then set up a reverse-proxy with Caddy, routing api.nkozak.com requests to port 4321.