Handle an HTTP request and shape an `HttpResult`
Goal: answer an HTTP request, reading path parameters and a request body, and return the right status.
Handlers go in a service inside a context. Each handler names a verb, a route,
its parameters, and returns Effect[HttpResult[T]].
A handler with no input
Section titled “A handler with no input”context notes
service api from http { on GET("/ping") by Visitor () -> Effect[HttpResult[String]] { Ok("pong") }}Ok("pong") is the HttpResult variant for 200 OK.
Read a path parameter
Section titled “Read a path parameter”A :name segment in the route becomes a parameter of the same name:
on GET("/notes/:id") by Visitor (id: String) -> Effect[HttpResult[String]] { NotFound }Accept a request body
Section titled “Accept a request body”A body parameter is parsed and validated from the request’s JSON before the
handler runs — an invalid body is rejected with 400 at the boundary:
type NewNote = { title: String }
service api from http { on POST("/notes") by Visitor (body: NewNote) -> Effect[HttpResult[NewNote]] { Created(body) }}Choose the right status
Section titled “Choose the right status”Return the HttpResult variant matching the outcome — Ok (200),
Created (201), Accepted (202), NoContent (204), a redirect such as
Found(url) (302) or SeeOther(url) (303), BadRequest(msg) (400),
Unauthorized (401), Forbidden (403), NotFound (404), Conflict(msg) (409),
UnprocessableEntity(msg) (422), TooManyRequests(msg) (429),
ServerError(msg) (500), ServiceUnavailable(msg) (503). See the
HTTP reference for the full table. Map domain errors
to statuses with match:
fn handle(ok: Bool) -> HttpResult[String] { if ok { Ok("done") } else { BadRequest("bad input") }}Stream an incremental response
Section titled “Stream an incremental response”To send a response as it is produced — a progress feed, a token relay, a live
tick — return Streaming(stream) instead of a buffered Ok(value). It carries a
Stream[String] and emits it as Server-Sent
Events (text/event-stream); each stream element is one data: event.
context feed
service Feed from http { on GET("/ticks") by Visitor () -> Effect[HttpResult[()]] { Streaming(Stream.of(["tick-1", "tick-2", "tick-3"]).take(3)) }}A streamed response returns Effect[HttpResult[()]] — there is no JSON body
value, so the parameter is (). Because the status is sent before the first
chunk, streaming is 200-only: decide any failure before you start, and
return an ordinary variant instead — it shares HttpResult[()], so both live in
one handler:
on GET("/feed/:mode") by Visitor (mode: String) -> Effect[HttpResult[()]] { if mode == "live" { Streaming(Stream.of(["a", "b", "c"]).take(2)) } else { NotFound }}See HTTP → Streamed responses for the framing rules and the mid-stream-error pattern.
Build and run
Section titled “Build and run”HTTP services compile to a Cloudflare Worker with --target workers. See
Target Cloudflare Workers.
Related
Section titled “Related”- Tutorial: Build a small HTTP service.
- Reference: HTTP — the complete variant/status table.