Response DSL
Apion provides extension methods and helper functions for concise response creation. These are available via import io.github.edadma.apion._.
Text Responses
Section titled “Text Responses”"Hello World".asText // Future[Complete] — 200 OK, text/plain"Created".asText(201) // Future[Complete] — 201 CreatedJSON Responses
Section titled “JSON Responses”Any type with a JsonEncoder instance:
case class User(name: String) derives JsonEncoder
User("Alice").asJson // Future[Complete] — 200 OK, application/jsonUser("Alice").asJson(201) // Future[Complete] — 201 CreatedWorks with Maps too:
Map("status" -> "ok").asJsonMap("error" -> "oops").asJson(400)Binary Responses
Section titled “Binary Responses”buffer.asBinary // Future[Complete] — 200 OK, application/octet-streambuffer.asBinary(200)Standalone Functions
Section titled “Standalone Functions”These return Future[Result] and can be used as handler return values:
// JSONjson(data) // 200 OKjson(data, 201) // 201 Created
// Texttext("Hello") // 200 OKtext("Created", 201) // 201 Created
// No contentnoContent // 204 No Content
// Created with optional Location headercreated(data) // 201 with JSON bodycreated(data, Some("/users/123")) // 201 with Location headerCommon Error Responses
Section titled “Common Error Responses”Pre-built responses for common HTTP errors:
notFound // 404 — {"error":"Not Found"}badRequest // 400 — {"error":"Bad Request"}serverError // 500 — {"error":"Internal Server Error"}Error Helpers
Section titled “Error Helpers”Create Fail results with typed errors:
skip // Future[Skip]fail(error) // Future[Fail(error)]failValidation("Bad input") // Future[Fail(ValidationError(...))]failAuth("Unauthorized") // Future[Fail(AuthError(...))]failNotFound("Not found") // Future[Fail(NotFoundError(...))]Result Extension Methods
Section titled “Result Extension Methods”Add headers to any Future[Result]:
"Hello".asText .withHeader("X-Custom", "value")
data.asJson .withHeaders( "X-Request-Id" -> id, "X-Duration" -> s"${ms}ms", )Response Extension Methods
Section titled “Response Extension Methods”Modify Response objects directly:
// Cookiesresponse.withCookie("session", "abc123")response.withCookie( name = "session", value = "abc123", maxAge = Some(3600), path = Some("/"), httpOnly = true, secure = true, sameSite = Some("Strict"),)response.withCookie(Cookie(name = "k", value = "v"))response.clearCookie("session")Complete Example
Section titled “Complete Example”server .get("/hello", _ => "Hello World".asText) .get("/user/:id", req => { findUser(req.params("id")) match { case Some(user) => user.asJson case None => failNotFound("User not found") } }) .post("/users", req => req.json[CreateUser].flatMap { case Some(data) => val user = createUser(data) created(user, Some(s"/users/${user.id}")) case None => failValidation("Invalid JSON body") }) .delete("/users/:id", req => { deleteUser(req.params("id")) noContent })