Documentation Index
Fetch the complete documentation index at: https://docs.prism.byescaleira.com/llms.txt
Use this file to discover all available pages before exploring further.
Content Negotiation
Not every client wants JSON. Browsers prefer HTML, spreadsheet tools want CSV, and some integrations need XML. Content negotiation lets a single endpoint serve multiple formats — the client’s Accept header decides which one.
How It Works
- Client sends
Accept: application/xml, application/json;q=0.9
- Prism parses and ranks the media types by quality factor
- Your available formats are matched against the client’s preferences
- The best match wins
Quick Example
await server.get("/status") { request in
let data: [String: Any] = [
"status": "healthy",
"uptime": 86400,
"version": "2.1.0"
]
return PrismNegotiatedResponse.respond(
to: request,
data: data,
available: [.json, .xml, .html, .csv, .text]
)
}
This single endpoint responds with JSON, XML, HTML table, CSV, or plain text — based on what the client asks for.
PrismResponseFormat.json // application/json
PrismResponseFormat.xml // application/xml
PrismResponseFormat.html // text/html — renders as HTML table
PrismResponseFormat.csv // text/csv — header row + values
PrismResponseFormat.text // text/plain — key=value pairs
PrismResponseFormat.custom("application/yaml")
PrismMediaType.parse handles the full Accept header spec — quality factors, wildcards, and multiple types:
let types = PrismMediaType.parse("text/html, application/json;q=0.9, */*;q=0.1")
// Sorted by quality: text/html (1.0), application/json (0.9), */* (0.1)
Manual Negotiation
For custom rendering logic, use PrismContentNegotiator directly:
await server.get("/users") { request in
let accept = request.headers.value(for: "Accept") ?? "application/json"
let format = PrismContentNegotiator.negotiate(
accept: accept,
available: [.json, .csv]
)
let users = try await fetchUsers()
switch format {
case .csv:
let csv = users.map { "\($0.id),\($0.name),\($0.email)" }.joined(separator: "\n")
let header = "id,name,email\n"
var headers = PrismHTTPHeaders()
headers.set(name: "Content-Type", value: "text/csv")
return PrismHTTPResponse(status: .ok, headers: headers, body: .text(header + csv))
default:
return .json(users)
}
}
Skip negotiation and render data in a known format:
// Force XML output
let response = PrismNegotiatedResponse.render(
data: ["name": "Alice", "role": "admin"],
as: .xml
)
// <?xml version="1.0" encoding="UTF-8"?>
// <root>
// <name>Alice</name>
// <role>admin</role>
// </root>
When no Accept header is present, PrismNegotiatedResponse defaults to JSON. When the client sends Accept: */*, the first format in your available list wins — so order your formats by preference.
The built-in HTML renderer creates a simple key-value table. For rich HTML, use content negotiation to detect when HTML is wanted, then render your own template.