Skip to content

Basic Routing

Routing is one of the most critical parts of a web framework. The router decides which requests get which responses.

Vapor has a plethora of functionality for routing including route builders, groups, and collections. In this section, we will look at the basics of routing.


The most basic route includes a method, path, and closure.

drop.get("welcome") { request in
    return "Hello"

The standard HTTP methods are available including get, post, put, patch, delete, and options."form") { request in
    return "Submitted with a POST request"


To nest paths (adding /s in the URL), simply add commas.

drop.get("foo", "bar", "baz") { request in
    return "You requested /foo/bar/baz"

You can also use /, but commas are often easier to type and work better with type safe route parameters.


An alternate syntax that accepts a Method as the first parameter is also available.

drop.add(.trace, "welcome") { request in
    return "Hello"

This may be useful if you want to register routes dynamically or use a less common method.


Each route closure is given a single Request. This contains all of the data associated with the request that led to your route closure being called.

Response Representable

A route closure can return in three ways:

  • Response
  • ResponseRepresentable
  • throw


A custom Response can be returned.

drop.get("vapor") { request in
    return Response(redirect: "")

This is useful for creating special responses like redirects. It is also useful for cases where you want to add cookies or other items to the response.

Response Representable

As you have seen in the previous examples, Strings can be returned in route closures. This is because they conform to ResponseRepresentable

A lot of types in Vapor conform to this protocol by default: - String - Int - JSON - Model

drop.get("json") { request in
    var json = JSON()
    try json.set("number", 123)
    try json.set("text", "unicorns")
    try json.set("bool", false)
    return json


If you are unable to return a response, you may throw any object that conforms to Error. Vapor comes with a default error enum Abort.

drop.get("404") { request in
    throw Abort(.notFound)

You can customize the message of these errors by using Abort

drop.get("error") { request in
    throw Abort(.badRequest, reason: "Sorry 😱")

These errors are caught by default in the ErrorMiddleware where they are turned into a JSON response like the following.

    error: true,
    message: "<the message>"

If you want to override this behavior, remove the ErrorMiddleware (key: "error") from the Droplet's middleware and add your own.


Fallback routes allow you to match multiple layers of nesting slashes.

app.get("anything", "*") { request in
    return "Matches anything after /anything"

For example, the above route matches all of the following and more:

  • /anything
  • /anything/foo
  • /anything/foo/bar
  • /anything/foo/bar/baz
  • ...