Server Side Swift using Vapor

Dimitri Tsiflitzis

7L International

Let's learn how to build and host our very first backend application using Vapor 4.

 

What is Vapor?

  • Vapor is an open source web framework.
  • It can be used to create RESTful APIs, web apps, and real-time apps using WebSockets.
  • Vapor provides an ORM, a templating language, and a plethora of packages to facilitate user authentication and authorisation.

Release history

Releases
Version Release date Swift version
1.0 Sep 15, 2016 ≥ 3.0
2.0 May 17, 2017 ≥ 3.1
3.0 May 4, 2018 ≥ 4.1
4.0 April 9, 2020 ≥ 5.2
5.0 TBD ≥ TBD

Curated list of Vapor projects

Honorable Mentions

Kitura

Installing Vapor 

  • xcode 9.0+
  • run swift --version (should be 5.0+)
# macOS
brew install vapor/tap/vapor

# linux
eval $(curl -sL https://apt.vapor.sh)
sudo apt-get update
sudo apt-get install vapor

Hello Vapor

vapor new myProject
cd myProject

// open xcode & run

Hello Vapor

import Vapor
 
let app = try Application(.detect())
defer { app.shutdown() }

app.get("hello") { req in
    return "Hello, world."
}

try app.run()

The architecture of a Vapor application

Run

  • The project is separated into two targets.
  • The first one is App and the second one is Run. 

The architecture of a Vapor application

App

  • Backend application code lives here.
  • It's a library package. It can be imported into the Run target.

The architecture of a Vapor application

Config

  • In the configure.swift file you can customise your application.
  • Register all the various services, middleware, set the router object, database connections etc

The architecture of a Vapor application

Routes

  • The routes.swift file is where you can add the routes for your router.

The architecture of a Vapor application

Controllers

  • Controllers are code organization tools.
  • Group related API endpoints together.
  • The router connects the endpoints by using this controller
  • The controller will query (create, request, update, delete) the appropriate models using the database connection.

The architecture of a Vapor application

Models

  • Vapor has a database abstraction tool called Fluent.
  • Models represent database entries usually related to this Fluent library.
  • In the sample project the Todo class defines the name of the database scheme as a static property.
  • Each field in the table has a corresponding property in the entity.

The architecture of a Vapor application

Migrations

  • Vapor 4 has added support for database migrations.
  • You can alter your database for the introduction of a new field or any other database alteration.

The architecture of a Vapor application

Tests

  • Vapor 4 includes a new testing framework called XCTVapor.
  • This framework makes easier to test your application with just a few lines of code.
  • The Tests folder you'll some basic test already setup. ✅

Tips & tricks for using to Vapor 4

  • Use a custom working directory in Xcode - otherwise DerivedData will be used (a terrible place)

Tips & tricks for using to Vapor 4

Using system provided directories

 

func configure(_ app: Application) throws {

print(app.directory.workingDirectory)
print(app.directory.publicDirectory)
print(app.directory.resourcesDirectory)
print(app.directory.viewsDirectory)

//...
}

Tips & tricks for using to Vapor 4

You can pass your secrets to a Vapor application by using environment variables. .env files! 🎉

func configure(_ app: Application) throws {
    let variable = Environment.get("EXAMPLE") ?? "undefined"
    print(variable)
    print(app.environment.name)
    print(app.environment.arguments)
    print(app.environment.commandInput)

    if app.environment.isRelease {
        print("production mode")
    }

    //...
}

Tips & tricks for using to Vapor 4

Change port number and hostname 

func configure(_ app: Application) throws {
    app.http.server.configuration.hostname = "127.0.0.1"
    app.http.server.configuration.port = 8081
    //...
}

Tips & tricks for using to Vapor 4

Router parameters

app.get("hello", ":world") { req -> String in
                            
    let param = req.parameters.get("world") ?? "default"
                            
    return "Hello, \(param.capitalized)!"
}

How to deploy & host your Swift server?

E.g. On AWS

  • You can use a T2.nano instance completely FREE for 1 year.
  • Instances are prepared super fast and you'll have a linux machine on AWS

 

How to run a Vapor 4 project using Docker?

The generated project will also include both a Dockerfile and a docker-compose.yml file

# Build image
FROM vapor/swift:5.2 as build
WORKDIR /build
COPY ./Package.* ./
RUN swift package resolve
COPY . .
RUN swift build --enable-test-discovery -c release -Xswiftc -g

# Run image
FROM vapor/ubuntu:18.04
WORKDIR /run
COPY --from=build /build/.build/release /run
COPY --from=build /usr/lib/swift/ /usr/lib/swift/
COPY --from=build /build/Public /run/Public
ENTRYPOINT ["./Run"]
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0"]

How to run a Vapor 4 project using Docker?

The Dockerfile separates the build and run process into two distinct images. 🐋

docker build -t vapor-image .

# simply run the container instance & bind the port
docker run --name vapor-server -p 8080:8080 vapor-image

# run the instance, bind the port, see logs remove after exit (CTRL+C)
docker run --rm -p 8080:8080 -it vapor-image

Further reading

Ευχαριστούμε, let's code 🎈