Server Side Swift using Vapor

Dimitri James Tsiflitzis

CocoaHeads

What is Vapor?

  • Vapor is a web framework for Swift.
  • Β It provides a beautifully expressive and easy to use foundation for your next website, API, or cloud project.

Curated list of Vapor projects

Honorable Mentions

Installing Vapor

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

Installing Vapor

  • On Linux(Ubuntu) we're available
  • https://docs.vapor.codes/3.0/install/ubuntu/

Hello vapor

  • type vapor new Hello
  • type cd Hello
  • type vapor xcode

In a terminal

Hello vapor

import Vapor

let app = try Application()
let router = try app.make(Router.self)

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

try app.run()

Toolbox

  • type vapor new Hello --template=api
  • cd Hello
  • type vapor xcode

In a terminal

SPM

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    name: "Hello",
    dependencies: [
        // πŸ’§ A server-side Swift web framework.
        .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),

        // πŸ”΅ Swift ORM (queries, models, relations, etc) built on SQLite 3.
        .package(url: "https://github.com/vapor/fluent-sqlite.git", from: "3.0.0-rc.2")
    ],
    targets: [
        .target(name: "App", dependencies: ["FluentSQLite", "Vapor"]),
        .target(name: "Run", dependencies: ["App"]),
        .testTarget(name: "AppTests", dependencies: ["App"])
    ]
)

Folder Structure

.
β”œβ”€β”€ Sources
β”‚   β”œβ”€β”€ App
β”‚   β”‚   └── (Source code)
β”‚   └── Run
β”‚       └── main.swift
β”œβ”€β”€ Tests
β”‚   └── AppTests
└── Package.swift

βœ‚οΈ Let's clean up the project a bit

Configure our own port

let service = NIOServerConfig.default(port: 8001)
services.register(service)

Add this to configuration.swift

My first route

/// Basic "Hello, world!" example
router.get("hello") { req in
    return "Hello, world!"
}

Let's get creative in the editor

Models

struct Employee : Content {

}

Note: We'll be using JSON but JSON, protobuf, URLEncodedForm, Multipart are all treated the same

Controllers

  • Controllers are a great way to organize your code.
  • Β They are collections of methods that accept a request and return a response.

Hello Controller

import Vapor

final class HelloController {
    func greet(_ req: Request) throws -> String {
        return "Hello!"
    }
}

Hello Controller usage

let helloController = HelloController()
router.get("greet", use: helloController.greet)

Add this to configuration.swift

POST request

  • First, create a struct or class that represents the data you expect.
import Vapor

struct LoginRequest: Content {
    var email: String
    var password: String
}

POST request

  • Now we are ready to decode that HTTP request.
router.post("login") { req -> Future<HTTPStatus> in
    return req.content.decode(LoginRequest.self)
           .map(to: HTTPStatus.self) { loginRequest in

        print(loginRequest.email) // user@vapor.codes
        print(loginRequest.password) // don't look!

        return .ok
    }
}

Further reading

ΕυχαριστούμΡ 🎈