Getting started with Vapor

Vapor is a web application framework written in Swift.

Installing on Linux

As I’m more likely to be using a Linux server for my web application, that’s what we’ll use for this post. So following the Install on Linux instructione, I went the route of installing the toolbox for the toolbox repo (instructions recreated below)

git clone https://github.com/vapor/toolbox.git
cd toolbox
git checkout <desired version>
make install

This will build and install vapor.

Generating an application

Vapor will generate an application for us using

vapor new hello-vapor -n

(obviously replace hello-vapor with your application name).

As we’re using Linux, we’ll cd into the hello-vapor application folder and then run

swift run

This will run, by default on localhost:8080 which is not great if you want to access remotely, so let’s instead start the application using

swift run Run --hostname 0.0.0.0 --port 8080

Now if you connect to the server’s ip address, port 8080 you should see the default return “It works!” if you use http://localhost:8080/hello you’ll see “Hello, world!” returned.

If you take a look at the source generated by Vapor and check the folder Sources/App/routes.swift you’ll see code like this

import Vapor

func routes(_ app: Application) throws {
    app.get { req in
        return "It works!"
    }

    app.get("hello") { req -> String in
        return "Hello, world!"
    }
}

As you can see this is routing the /hello GET method to return “Hello, world!”.

Using HTTP methods

As you can see from the previous code, app.get denotes the method is a GET method, so let’s simply write an example of each of the HTTP methods, so change your routes.swift file to add the following

app.get("method") { req -> String in
   return "\(req)"
}

app.post("method") { req -> String in
   return "\(req)"
}

app.put("method") { req -> String in
   return "\(req)"
}

app.patch("method") { req -> String in
   return "\(req)"
}

app.delete("method") { req -> String in
   return "\(req)"
}

This doesn’t cover all HTTP methods, but we can use the alternate syntax to the above, which looks like this

app.on(.GET, "method") { req -> String in
   return "\(req)"
}

and simply replace .GET with each of the HTTP methods, such as .CONNECT, .OPTIONS, etc.

Now let’s tests these – if we simply use CURL to execute each method, i.e.

curl -X GET localhost:8080/method
curl -X POST localhost:8080/method
curl -X PUT localhost:8080/method
curl -X PATCH localhost:8080/method
curl -X DELETE localhost:8080/method

Parameters and Query Parameters

We’re also likely to need to handle parameters, so for example /method/aparam

app.get("method", ":param") { req -> String in
   let param = req.parameters.get("param")!        
   return "\(param) --> \(req)"
}

The : prefixing the param token is indicates the parameter is dynamic and hence we need to use req.parameters.get(“param”)! to get the value from the param.

Finally for this post, what about if we want to pass query parameters, for example http://192.168.0.88:8080/method?firstName=Scooby&lastName=Doo

We can declare a struct to handle our expected query parameters like this

struct Person: Content {
    var firstName: String?
    var lastName: String?
}

and now change our GET method to decode the query parameters into this struct, for example

app.get("method") { req -> String in
   let person = try req.query.decode(Person.self)
   return "Firstname: \(person.firstName!), Lastname \(person.lastName!)"
}

There’s a whole lot more functionality, as you’d expect, including streaming, validation etc. take a look at the Vapor Docs.