Week 2

Follow Vapor Nation on Twitter 😲

It’s a big week for Vapor! With the finalization of tagged beta releases on February 9th, you can finally update without worrying (too much) about it breaking your project. In addition to everything in this week’s Vapor Nation, there were loads of bug fixes and minor improvements behind the scenes, so if you were holding off because of a blocking bug before, now would be a good time to update your projects and give it another shot. Without further ado, let’s get into it!


map and flatmap Explicit Return Type

Should map and flatmap require an explicit return type when their input is the same type as their output?


catchMap Naming and Behavior

Should there be a way to catch specific errors in promise chains? What should it be called?


New Features

Next Tick

Adds eventLoop.onNextTick { ... }, promise.complete(..., onNextTick: ...), and worker.doBlockingWork { ... }, which should prevent stack overflows in some cases.


Community Contributions

Massive overhaul of mismanaged memory in Engine

@gwynne submitted a pretty huge PR that fixes several bugs, including:

The PR also adds handling of the version field on Request, allowing Clients to send HTTP/1.0 requests. (300 LoC)


Add header names and use constants where possible

@siemensikkema noticed a few missing HTTP headers, so they added them in. They also increased safety by replacing string literals with constants where possible. (9 LoC)


Code Cleanup

@siemensikkema was busy this week! They went through and updated comments and removed blank lines where possible, greatly improving code cleanliness. (50 LoC)



Very important PR that adds a missing HTTP code. (1 LoC)


Fixed Exclusive Access to Memory

Swift 4.1 introduced the requirement that exclusive memory access be enforced on a per-line basis. Most people felt this was overall a good change, but there were a few places in the Vapor codebase that the rule wasn’t being followed, preventing compilation with the latest 4.1 toolchains. @SandorDobi fixed that. (20 LoC)


Switched to Tagged Dependencies for JWT and Leaf

With the deadline for tagging being this week, there was a lot of work to do. @tanner0101 did most of it for the core Vapor repos, but @Cellane came through with the cleanup.



Joannis’ explanation on SO

@Joannis gave a short overview of Vapor 3 in response to a question on Stack Overflow.



Vapor Meetup Tokyo

As Vapor ramps up, I’m expecting to see more and more talks, and the first Vapor 3 talks come to us out of Tokyo! At the meetup, @tanner0101 gave us an introduction to Vapor and the benefits of Swift on the server (English), @Joannis talks about what makes Vapor fast and efficient (English), @noppoMan talked about their experience with serverless Swift (Japanese), @Casperhr talks about running Vapor in production (English), and @hiragram led us through the path he took making the backend for his cryptocurrency app with Vapor (Japanese).


Made With Vapor


Vapor is about a week away from passing Perfect in the number of Github stars! While this isn’t the most important metric, it will make Vapor the most popular server-side Swift framework on Github. You can track the momentous occasion using http://serversideswift.racing/ made by @MartinLasek! Check it out 😊



Vapor’s Futures encourage a style of coding that’s all about data transformation. You take in a request, turn that request into an ID, use that ID to search the database for a row, turn that row into an object, make some change to that object, turn that object into a response, and return that response. Every input gets sent down a pipeline until you end up with the data you want. The map(to:) function is the building block of all transformations. So what does that look like?

router.get("user", UUID.parameter) { (req) -> Future<Response> in // Take in a request
    let userID = try req.parameter(UUID.self) // Turn that request into an ID

    return try User
        .find(userID, on: req) // Use that ID to search the database for a row, turn that row into an (optional) object
        .map(to: User.self) { (user) in // Unwrap the object
            guard let user = user else {throw Abort(.notFound, reason: "User Not Found")}
            return user
        }.map(to: User.self) { (user) in // Make some change to the object
            user.name = "Jamie"
            return user
        }.encode(for: req) // Turn that object into a response, and return that response


@gwynne @twof