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.
Routing
Prismβs router matches incoming requests to handlers using URL patterns. It supports path parameters, wildcards, route groups, and nested prefixes.
Basic Routes
Register routes with the HTTP method and a URL pattern:
await server. get ( "/" ) { _ in . text ( "Home" ) }
await server. get ( "/about" ) { _ in . text ( "About" ) }
await server. post ( "/contact" ) { _ in . json ([ "sent" : true ]) }
You can also use the generic route method:
await server. route (. PATCH , "/users/:id" ) { request in
. json ([ "patched" : true ])
}
Path Parameters
Capture dynamic URL segments with :paramName:
await server. get ( "/users/:id" ) { request in
let userId = request. parameters [ "id" ] !
return . json ([ "user" : userId])
}
// Multiple parameters
await server. get ( "/teams/:teamId/members/:memberId" ) { request in
let teamId = request. parameters [ "teamId" ] !
let memberId = request. parameters [ "memberId" ] !
return . json ([ "team" : teamId, "member" : memberId])
}
Parameters are always strings. Parse them in your handler: Int(request.parameters["id"]!) for integers.
Wildcards
The * wildcard matches any remaining path:
// Matches /files/photo.jpg, /files/docs/report.pdf, etc.
await server. get ( "/files/*" ) { request in
let filePath = request. path . replacingOccurrences ( of : "/files/" , with : "" )
return . text ( "Serving: \( filePath ) " )
}
Route Groups
Group related routes under a shared prefix. Groups can have their own middleware:
await server. group ( "/api" ) { api in
api. get ( "/status" ) { _ in . json ([ "status" : "ok" ]) }
// Nested group with auth
api. group ( "/admin" , middlewares : [authMiddleware]) { admin in
admin. get ( "/users" ) { _ in . json ([ "users" : []]) }
admin. post ( "/users" ) { _ in . json ([ "created" : true ]) }
admin. delete ( "/users/:id" ) { request in
. text ( "Deleted \( request. parameters [ "id" ] ! ) " )
}
}
}
This produces:
GET /api/status β no auth required
GET /api/admin/users β auth required
POST /api/admin/users β auth required
DELETE /api/admin/users/:id β auth required
REST Resource Pattern
A common pattern for building RESTful APIs:
await server. group ( "/api/v1" ) { api in
// Products resource
api. get ( "/products" ) { request in
let page = Int (request. queryParameters [ "page" ] ?? "1" ) ?? 1
let products = try db. query (
"SELECT * FROM products LIMIT 20 OFFSET ?" ,
parameters : [. integer ((page - 1 ) * 20 )]
)
return . json ([ "products" : products. map { $0 . columns }, "page" : page])
}
api. get ( "/products/:id" ) { request in
guard let row = try db. queryFirst (
"SELECT * FROM products WHERE id = ?" ,
parameters : [. text (request. parameters [ "id" ] ! )]
) else {
throw PrismAppError. notFound ( "Product not found" )
}
return . json (row. columns )
}
api. post ( "/products" ) { request in
guard let body = request.body,
let json = try ? JSONSerialization. jsonObject ( with : body) as? [ String : Any ],
let name = json[ "name" ] as? String else {
throw PrismAppError. badRequest ( "Missing product name" )
}
try db. execute (
"INSERT INTO products (name) VALUES (?)" ,
parameters : [. text (name)]
)
return . json ([ "name" : name], status : . created )
}
api. delete ( "/products/:id" ) { request in
try db. execute (
"DELETE FROM products WHERE id = ?" ,
parameters : [. text (request. parameters [ "id" ] ! )]
)
return PrismHTTPResponse ( status : . noContent )
}
}
Route Priority
Routes are matched in registration order. The first match wins:
// This matches first for "/users/me"
await server. get ( "/users/me" ) { _ in . json ([ "user" : "current" ]) }
// This matches "/users/123", "/users/abc", etc.
await server. get ( "/users/:id" ) { request in
. json ([ "user" : request. parameters [ "id" ] ! ])
}
Register specific routes before parameterized ones. /users/me should come before /users/:id, otherwise :id will capture βmeβ as a parameter.
Query Parameters
Query parameters are automatically parsed from the URL:
// GET /search?q=swift&page=2
await server. get ( "/search" ) { request in
let query = request. queryParameters [ "q" ] ?? ""
let page = Int (request. queryParameters [ "page" ] ?? "1" ) ?? 1
return . json ([ "query" : query, "page" : page])
}
Request Learn how to extract data from incoming requests.
Middleware Add cross-cutting concerns to route groups.