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.