Skip to content

Response

The Response is an immutable case class representing an HTTP response.

case class Response(
status: Int = 200,
headers: ResponseHeaders = ResponseHeaders.empty,
body: ResponseBody = EmptyBody,
)

The Response companion object provides factory methods for common response types:

case class User(name: String) derives JsonEncoder
Response.json(User("Alice")) // 200 with JSON body
Response.json(User("Alice"), status = 201) // 201 Created
Response.json(Map("error" -> "oops"), status = 400)
Response.text("Hello World") // 200 with text/plain
Response.text("Created", status = 201)
Response.binary(buffer) // 200 with application/octet-stream
Response.binary(buffer, status = 200)
val fileStream = fs.createReadStream("video.mp4")
Response.stream(fileStream, additionalHeaders = Seq(
"Content-Type" -> "video/mp4"
))
Response.noContent() // 204 with empty body
sealed trait ResponseBody
case class StringBody(content: String, data: Buffer) extends ResponseBody
case class BufferBody(content: Buffer) extends ResponseBody
case class ReadableStreamBody(readable: ReadableStream) extends ResponseBody
case object EmptyBody extends ResponseBody

ResponseHeaders is a case-insensitive, multi-value header container:

// Add a single header
response.copy(headers = response.headers.add("X-Custom", "value"))
// Add multiple headers
response.copy(headers = response.headers.addAll(Seq(
"Cache-Control" -> "no-cache",
"X-Request-Id" -> "abc123"
)))
// Read a header
response.headers.get("content-type") // Option[String]
response.headers.contains("x-custom") // Boolean
// Remove a header
response.copy(headers = response.headers.remove("x-custom"))

Headers are normalized with smart casing — content-type becomes Content-Type, common acronyms like API, JWT, CORS are uppercased correctly.

Every response includes these headers automatically:

HeaderValue
ServerApion
Cache-Controlno-store, no-cache, must-revalidate, max-age=0
Pragmano-cache
Expires0
X-Powered-ByApion
DateRFC 1123 formatted current time

Configure or override defaults:

Response.configure(Seq(
"Server" -> "MyApp",
"X-Powered-By" -> "MyApp"
))
// Reset to defaults
Response.resetDefaultHeaders()

Set cookies on responses using extension methods:

// Simple cookie
response.withCookie("session", "abc123")
// Cookie with attributes
response.withCookie(
name = "session",
value = "abc123",
maxAge = Some(3600), // 1 hour
path = Some("/"),
secure = true,
httpOnly = true,
sameSite = Some("Strict")
)
// Using a Cookie object
response.withCookie(Cookie(
name = "session",
value = "abc123",
maxAge = Some(3600),
httpOnly = true
))
// Clear a cookie
response.clearCookie("session")

Add headers to a Future[Result]:

"Hello".asText.withHeader("X-Custom", "value")
data.asJson.withHeaders(
"X-Request-Id" -> requestId,
"X-Duration" -> s"${duration}ms"
)

For testing or inspection:

response.bodyText // String content of the response body