Routing
Routes in Vapor can be defined in any file that has access to your instance of Application. This is usually in the main.swift file.
Basic
The most basic route includes a method, path, and closure.
app.get("welcome") { request in
return "Hello"
}
The standard HTTP methods are available including get, post, put, patch, delete, and options.
You can also use any to match all methods.
Request
The first parameter passed into your route closure is an instance of Request. This contains the method, URI, body, and more. Learn more about Request in the Request section of this guide.
let method = request.method
JSON
To respond with JSON, simply wrap your data structure with JSON()
app.get("version") { request in
return JSON(["version": "1.0"])
}
Response Representable
All routing closures can return a ResponseRepresentable data structure. By default, Strings and JSON conform to this protocol, but you can add your own.
public protocol ResponseRepresentable {
func makeResponse() -> Response
}
Visit the Response section to learn more.
Parameters
Parameters are described by passing the type of data you would like to receive.
app.get("hello", String) { request, name in
return "Hello \(name)"
}
When you add a parameter type, like String, the closure will be required to contain another input variable. This variable will be the same type. In this case, String.
String Initializable
Any type that conforms to StringInitializable can be used as a parameter. By default, String and Int conform to this protocol, but you can add your own.
struct User: StringInitializable {
...
}
app.get("users", User) { request, user in
return "Hello \(user.name)"
}
Using Swift extensions, you can extend your existing types to support this behavior.
extension User: StringInitializable {
init?(from string: String) throws {
guard let int = Int(string) else {
return nil //Will Abort.InvalidRequest
}
guard let user = User.find(int) else {
throw UserError.NotFound
}
self = user
}
}
You can throw your own errors or return nil to throw the default error. Learn more about errors in the Error Handling section of this guide.
Groups
Prefix a group of routes with a common string using grouped(_: String).
app.grouped("v1") { v1 in
v1.get("users") { request in
return User.all
}
}
Grouped Middleware
In addition to grouping by endpoints, one can also group middleware to only apply to routes in scope.
app.grouped(AuthMiddleware(), UserMiddleware()) { group in
group.get("token") { req in
return getToken(req)
}
}
Caveats
Type-safe routing supports up to five parameters.
app.get("users", User, "posts", Post, "comments") { request, user, post in
//this is the maximum
}
Exceeding five parameters is unlikely if you use app.group and app.host. You can also include slashes in fixed route sections.
app.get("v1/users", User, "resources/written/posts", Post) { request, user, post in
//only four parameters used here
}
Additionally, due to a bug in the compiler, .self is sometimes required after type names. To circumvent this, you can trick the compiler by using:
let Int = Swift.Int.self
let String = Swift.String.self
Support the Swift evolution pull request to fix this behavior.
Update: This has since been approved
Custom Routing
Vapor still supports traditional routing for custom use-cases or long URLs.
app.get("users/:user_id") { request in
request.parameters["user_id"] // Optional<String>
}
Updated less than a minute ago
