These docs are for v0.12. Click to read the latest docs for v0.16.

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>
}