Routing in Vapor 2.0, Part 1: Basic Routing

Hello droplets! Routing is one of the core functions of any backend framework. It is quite simple and elegant with vapor. So let's begin!

Create a new Vapor project, called Routing, by running:

$ vapor new Routing --template=api

Then run vapor xcode to create the Xcode project, and press y when prompted to open the Xcode project.

First, delete the Post.swift file and the PostController.swift file, we will not be using them. Then, in the setupPreparations() method, in Config+Setup.swift , delete the line preparations.append(Post.self) .

This entire tutorial will take place in Routes.swift . Delete all of the content from the setupRoutes() function.

Basic route

First, let's make a simple GET request. add the following route to setupRoutes() :

get("hello") { request in return "Hello, Vaporists!" }

The get function is called on our instance of droplet . All routes in vapor are called from the instance of our droplet.

Every route in vapor has 3 things:

A method (get, post, put, patch, delete)

A path, supplied by the user ( `"hello"` in our case)

a closure with the request

Also, we may notice that we returned a string. Every route closure in Vapor can return 1 of 3 ways:

a Response

a type conforming to the ResponseRepresentable protocol

protocol throw an error that conforms to Vapor.error

Nesting Routes

Nesting a hard-coded route is quite simple in vapor. Add the following to setupRoutes() :

get("hi/how/are/you") { request in return "this path is /hi/how/are/you" }

Custom Response:

We can also return a custom Response object as well. First, add import HTTP to the top of your Routes.swift file. Now, for example, we can redirect:

get("foo") { request in return Response(redirect: "https://apple.com") }

Navigating to /foo will now redirect you to the Apple website.

or we can return a certain status:

get("bar") { request in return Response(status: Status.forbidden) }

Like Status.forbidden , we can also return other instances of the Status enum. Some of the more common ones are:

Status.accepted Status.authenticationTimeout Status.badRequest Status.badGateway Status.created Status.notFound

Or, we can return a Response with a status and customized JSON:

get("vapor") { request in return try Response(status: Status.accepted, json: JSON(node: ["yourStatus here": "hello world!"])) }

Parameters

Oftentimes we need routes such as /posts/1 , for showing a post with an id of 1, or /posts/1/comments to show the post's comments. Vapor handles this very elegantly with its type-safe Parameterizable protocol:

get("post", Int.parameter) { request in let parameter = try request.parameters.next(Int.self) return "You requested route /post/\(parameter)" } get("post", Int.parameter, "comments") { request in let parameter = try request.parameters.next(Int.self) return "You requested route /post/\(parameter)/comments" }

With the Parameterizable protocol, any type that conforms to it can be represented as a parameter as above. If your uniqueId is not an int, but a string, that is also Parameterizable:

get("heart", String.parameter) { request in let parameter = try request.parameters.next(String.self) return "You requested route /heart/\(parameter)" }

Part 2 of this series on Routing in vapor will go more in depth on the Parameterizable protocol, and how we can use it with our models to efficiently retrieve objects.

Fallback Routes

A fallback route is defined in vapor as follows:

get("foobarbaz", "*") { request in // this route matches: // /foobarbaz/1 // /foobarbaz/1/2/3 return "this is a fallback route" }

As the second parameter, simply put a "*", and the route will match anything, as long as it begins with foobarbaz

Groups

If we need to put multiple routes underneath one common route, for example /v1/users and /v1/posts and /v1/comments , we can easily group them:

group("v1") { v1 in v1.get("users") { request in return "this route is /v1/users" } v1.get("comments") { request in return "this route is /v1/comments" } }

Alternatively, you can do the exact same as above, using this syntax:

let v1 = grouped("v1") v1.get("users") { request in return "this route is /users/all" } v1.get("comments") { request in return "this route is /users/none" }

And of course, you can combine different types of routes as well, such as grouping and parameters:

v1.get("users", Int.parameter) { request in let parameter = try request.parameters.next(Int.self) return "You requested /v1/users/\(parameter)" }

That's it for this beginning tutorial to routing in Vapor 2! Check back soon for Part 2 of the series, which will focus on using the Parameterizable protocol with your models, organizing your routes in controllers, and route collections. Thanks for reading!