# What's New in Vapor 4

**URL:** <https://forums.swift.org/t/whats-new-in-vapor-4/31832>\
**Category:** Vapor\
**Created:** [December 19, 2019, 12:39am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832 "2019-12-19T00:39:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![tanner0101](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tanner0101/32/675_2.png) [@tanner0101](https://forums.swift.org/u/tanner0101)\
**Post date:** [December 19, 2019, 12:39am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/1 "2019-12-19T00:39:54Z")

</div>

# What's New in Vapor 4

We've been working on the fourth major release of [Vapor](https://github.com/vapor/vapor) for almost a year now. The first alpha version was tagged last May, with the first beta following in October. During that time, the community has done amazing work helping to test, improve, and refine this release. Over [500 issues and pull requests](https://github.com/orgs/vapor/projects/2) have been closed so far!

Looking back at Vapor 3's pre-release timeline, 7 months passed between `alpha.1` and the final release. If history repeats itself, we would reach `4.0.0` sometime in February 2020.

As we near the end of the active development phase, efforts are shifting toward a focus on documentation and polish. Since APIs have mostly settled down at this point, I'd like to take this opportunity to introduce you to some of the exciting changes coming in Vapor 4. Let's dive in.

## New Dependency Injection API

Vapor 3 introduced `Services`, a pure Swift configuration framework which replaced Vapor 2's JSON configuration files. In Vapor 4, we're taking this a step further by leveraging the compiler to make configuring Vapor apps as easy as possible.

Vapor 4's new dependency injection API is now based on Swift extensions rather than type names. This makes services offered by third party packages - and Vapor itself! - more discoverable and feel more Swift-native.

How this works is best explained by example, so let's take a look at some common use cases of the Services API in Vapor 3 and what they would look like in Vapor 4.

### Changing the Default HTTP Port

In Vapor 3, changing the default HTTP port required overriding the default `NIOServerConfig` by registering your own:

```swift
// vapor 3
services.register(NIOServerConfig.self) { _ in
    return NIOServerConfig.default(port: 1337)
}

```

In Vapor 4, the server configuration is exposed as a mutable property on `Application`:

```swift
// vapor 4
app.server.configuration.port = 1337

```

### Making Leaf the View Renderer

In Vapor 3, the `Leaf` provider required registering a `LeafConfig` struct to `Services`. In order to tell Vapor to use Leaf by default, a preference was added to the `Config` struct:

```swift
// vapor 3
services.register(LeafConfig.self) { _ in
    return LeafConfig(...)
}
config.prefer(LeafRenderer.self, for: ViewRenderer.self)

```

In Vapor 4, `Leaf`'s configuration is another settable property on `Application`. A new `app.views` property makes it easy to tell Vapor which View Renderer to use with the `use` method:

```swift
// vapor 4
app.leaf.configuration = LeafConfiguration(...)
app.views.use(.leaf)

```

## NIO 2

Vapor 4 upgrades to [SwiftNIO](https://github.com/apple/swift-nio) 2.0. This release includes tons of great quality of life improvements, performance enhancements, and awesome features like vendored BoringSSL and pure Swift HTTP/2 implementation.

## SSWG

A huge focus for this release was integration with the new [Swift Server Working Group](https://swift.org/server/) (SSWG) ecosystem. Vapor joined forces with Apple to help define common standards for core fuctionality like [Logging](http://github.com/apple/swift-log) and [Metrics](http://github.com/apple/swift-metrics). Vapor 4 has adopted these new standards with open arms. What this means for you is great logging, metrics, and (soon) tracing that works seamlessly across all of your packages.

Vapor 4's Postgres driver was the first non-Apple package to go through the SSWG's proposal process and become an accepted project. The [SSWG incubation process](https://github.com/swift-server/sswg/blob/master/process/incubation.md) is designed to improve the overall quality and compatibility of the server-side Swift ecosystem. Vapor 4's MySQL driver is in the early stages of proposal, with many more packages to come in the future.

Thanks to efforts by the SSWG and wonderful contributions from the community, Vapor 4 will be the first release to depend on packages from authors other than Vapor and Apple. Namely [swift-server/async-http-client](https://github.com/swift-server/async-http-client), [mordil/swift-redi-stack](https://github.com/Mordil/swift-redi-stack), and [kylebrowning/APNSwift](https://github.com/kylebrowning/APNSwift). We look forward to continuing this trend going forward.

## Async HTTP Client

[AsyncHTTPClient](https://github.com/swift-server/async-http-client) is a new pure Swift HTTP client built on top of Swift NIO. This package is intended as a more perfomant and lightweight alternative to `URLSession`, especially on Linux. Vapor 4 has adopted this package, replacing `URLSession` as the framework's default HTTP client

## New `vapor new`

Vapor 4's toolbox includes an improved `vapor new` command that helps customize newly generated projects. Rather than choosing from a limited set of pree-existing templates, the `new` command will now ask you which packages you want to include in your new project and produce sample code tailored to your choices. For example, if you select both Fluent and JWT, sample code can be included showing how to integrate the packages together.

```sh
$ vapor new hello-world
Would you like to use Fluent? [y/n]:

```

## New Model API

Fluent 4's model API has been redesigned to take advantage of [property wrappers](https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md) in Swift 5.1. Property wrappers give Fluent much more control over how models work internally, which has been key to enabling long-requested features like a concise API for eager loading.

When declaring models, fields are now declared using the `@Field` property wrapper. Identifiers use the special `@ID` wrapper:

```swift
final class Galaxy: Model {
    @ID(key: "id")
    var id: UUID?

    @Field(key: "name")
    var name: String
}

```

Relations are declared with the property wrappers `@Parent`, `@Children`, and `@Siblings`:

```swift
final class Planet: Model {
    @ID(key: "id")
    var id: UUID?

    @Field(key: "name")
    var name: String

    @Parent(key: "galaxy_id")
    var galaxy: Galaxy
}

final class Galaxy: Model {
    ...

    @Children(for: \.$galaxy)
    var planets: [Planet]
}

```

### Eager Loading

Fluent can now preload a model's relations right from the query builder. Models will automatically include eager-loaded relations when serializing to `Codable` encoders.

Using the example from above, a `Fluent` query can eager-load its `Galaxy` parent with the `.with()` query builder method:

```swift
let planets = try Planet.query(on: db).with(\.$galaxy).all().wait()
for planet in planets {
    print(planet.galaxy) // Galaxy
}

```

The JSON output for this array of planets might look something like this:

```json
[
    {
        "id": ...,
        "name": "Earth",
        "galaxy": {
            "id": ...,
            "name": "Milky Way"
        }
    },
    ...
]

```

### Partial Reads & Updates

Fluent's new model API also makes it possible to do partial reads and updates on the database. When models fetched from the DB are updated and saved, Fluent now sends only the updated field values to the database.

## XCTVapor

Vapor 4 includes a new testing framework that makes it easier to test your application using `XCTest`. Importing `XCTVapor` adds `test` methods to your application that you can use to easily send requests:

```swift
import XCTVapor

app.test(.GET, to: "hello") { res in
    XCTAssertEqual(res.status, .ok)
    XCTAssertEqual(res.body.string, "Hello, world!")
}

```

Applications are tested in-memory by default. To boot an HTTP server and run the tests through an HTTP client, use `testable`:

```swift
app.testable(method: .running).test(.GET, to: ...) {
    // verify response
}

```

## HTTP/2 & TLS

Support for HTTP/2 and TLS is now shipped by default with Vapor 4. HTTP/2 support can be enabled by adding `.two` to the HTTP server's supported version set:

```swift
app.server.configuration.supportVersions = [.two]

```

TLS can be enabled by setting the server's TLS configuration struct:

```swift
app.server.configuration.tlsConfiguration = .forServer(...)

```

It's important to not that hosting your app behind a reverse-proxy like NGINX is still strongly recommended in production.

## Synchronous Content

Vapor's `Content` APIs now operate synchronously:

```swift
let newUser = try req.content.decode(CreateUser.self)
print(newUser) // CreateUser

```

This improvement is thanks to a new default policy on route handlers to collect streaming HTTP bodies _before_ calling the handler. HTTP body collection can be disabled when registering routes:

```swift
app.on(.POST, "streaming", body: .stream) { req in
    // req.body.data may be nil
    // use req.body.collect
}

```

## Backpressure

In addition to new request body collection strategies, request body streaming now supports backpressure. `req.body.drain()`, which streams incoming body data, now returns a `EventLoopFuture`. Until this future is completed, further request body chunks will not be transferred from the operating system. This allows Vapor apps to stream extremely large files directly to disk without ballooning memory.

Vapor's multipart parsing package `MultipartKit` has been rewritten to support streaming `multipart/form-data` uploads. This allows you can benefit from backpressure with both direct and form-based file uploads.

## Graceful Shutdown

Close attention to graceful shutdown has been given to all Vapor types that deal with long-lived resources. `Application` and many other types now have `close()` or `shutdown()` methods which must be called before they deinitialize:

```swift
let app = Application()
defer { app.shutdown() }

```

Requiring explicit shutdown methods is a pattern adopted from SwiftNIO and often helps reduce bugs. These shutdown methods also help prevent reference cycles from leaking memory in your application.

Alongside stricter adherence to good graceful shutdown practices, Vapor's HTTP server now supports NIO's `ServerQuiescingHelper` by default. This handler helps to ensure that any in-flight HTTP requests are given time to complete after a server initiates shutdown.

## New Command API

Vapor's `Command` APIs have also seen improvements thanks to property wrappers. `Command`s now define a `Signature` struct which uses wrapped properties to declare accepted arguments. When the command is run, the signature is decoded automatically and passed to the run function.

Available property wrappers are `@Argument`, `@Option`, and `@Flag`:

```swift
final class ServeCommand: Command {
    struct Signature: CommandSignature {
        @Option(name: "hostname", short: "H", help: "Set the hostname")
        var hostname: String?

        @Option(name: "port", short: "p", help: "Set the port")
        var port: Int?

        @Option(name: "bind", short: "b", help: "Set hostname and port together")
        var bind: String?
    }

    func run(using context: CommandContext, signature: Signature) throws {
        print(signature.hostname) // String?
    }
}

```

## APNS

A new [APNS](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html) integration package will ship its first release alongside Vapor 4. This package is built on the great work done by Kyle Browning with [APNSwift](https://github.com/kylebrowning/APNSwift).

This package integrates `APNSwift` into Vapor's application and request types, making it easy to configure and use:

```swift
import APNS
import Vapor

try app.apns.configuration = .init(
    keyIdentifier: "...",
    teamIdentifier: "...",
    signer: .init(file: ...),
    topic: "codes.vapor.example",
    environment: .sandbox
)

app.get("send-push") { req -> EventLoopFuture<HTTPStatus> in
    req.apns.send(
        .init(title: "Hello", subtitle: "This is a test from vapor/apns"),
        to: "..."
    ).map { .ok }
}

```

This new package is located at [vapor/apns](https://github.com/vapor/apns).

## Leaf Syntax

As first [described](https://forums.swift.org/t/pitch-new-leaf-body-syntax/18188) on the Swift forums, Leaf's new body syntax is complete and will ship with Vapor 4.

This change replaces Leaf's usage of curly braces with an `#end` prefix syntax:

```leaf
#for(user in users)
   Hello #(user.name)!
#endfor

```

Leaf 4 also has new syntax for template inheritance:

base.leaf:

```html
<html>
    <head><title>#import("title")</title><head>
    <body>#import("body")</body>
</html>

```

hello.leaf:

```leaf
#extend("base"):
    #export("title", "Welcome")
    #export("body"):
        Hello, #(name)!
    #endexport
#endextend

```

And the result when compiled with the context `["name": "Vapor"]`:

```html
<html>
    <head><title>Welcome</title><head>
    <body>Hello, Vapor!</body>
</html>

```

## Jobs

`Jobs`, a task queuing system for Vapor, will have its 1.0 release alongside Vapor 4. This package allows you to define job handlers for running long-running tasks in a separate process. Your Vapor route handlers can quickly dispatch jobs to these handlers to keep your application fast without compromising error handling.

Job handlers are declared using the `Job` protocol and must implement a `dequeue` method:

```swift
struct Email: Codable {
    var to: String
    var message: String
}

struct EmailJob: Job {
    func dequeue(_ context: JobContext, _ email: Email) -> EventLoopFuture<Void> {
        print("sending email to \(email.to)")
        ...
    }
}

```

Job handlers are then configured using `Jobs`' convenience APIs:

```swift
import Jobs
import Vapor

app.jobs.add(EmailJob())

```

Start the job handling process(es) using the new `jobs` command:

```sh
swift run Run jobs

```

Once set up, jobs can easily be dispatched from route handlers, using the `Request`:

```swift
app.get("send-email") { req in
    req.jobs.dispatch(EmailJob.self, Email(...))
        .map { HTTPStatus.ok }
}

```

Once dispatched, the job will be later dequeued and run in the separate jobs process. If any errors occur, the `EmailJob` handler will be notified.

Jobs also supports scheduling jobs to run at certain times using a new, fluent schedule building API:

```swift
// weekly
app.jobs.schedule(Cleanup())
    .weekly()
    .on(.monday)
    .at("3:13am")

// daily
app.jobs.schedule(Cleanup())
    .daily()
    .at("5:23pm")

// hourly
app.jobs.schedule(Cleanup())
    .hourly()
    .at(30)

```

This new package is located at [vapor/jobs](https://github.com/vapor/jobs).

## OpenCrypto

Vapor 3's crypto package has been refactored to mirror Apple's `CryptoKit` APIs. This package is now called [OpenCrypto](https://github.com/vapor/open-crypto/) and still depends on linking the system's OpenSSL. This change makes it easier for Apple platform developers to use Vapor's crypto APIs and significantly reduces maintenance complexity.

Furthermore, packages that require crypto functionality will now be able to target both server-side use cases and platforms that don't support linking OpenSSL (like iOS) by dynamically importing either `CryptoKit` or `OpenCrypto`:

```swift
#if canImport(CryptoKit)
import CryptoKit
#else
import OpenCrypto
#endif

let digest = try SHA512.hash(data: ...)

```

## JWT

A new package integrating Vapor and [JWTKit](https://github.com/vapor/jwt-kit) will ship alongside Vapor 4. This package is called [JWT](https://github.com/vapor/jwt) and makes it easy to sign and verify JSON Web Tokens from your application:

```swift
import JWT
import Vapor

try app.jwt.signers.use(.es512(key: .generate()))

app.post("login") { req -> LoginResponse in
    let credentials = try req.content.decode(LoginCredentials.self)
    return try LoginResponse(
        token: req.jwt.sign(User(name: credentials.name))
    )
}

app.get("me") { req -> String in
    try req.jwt.verify(as: User.self).name
}

```

## Docker

[vapor/docker](https://github.com/vapor/docker) is now home to several useful Docker images for working with Vapor.

### vapor/swift

These images are for building Vapor projects. They are based on `swift` images and include additional dependencies Vapor needs to build, such as OpenSSL and ZLib.

### vapor/ubuntu

These images are for running compiled Vapor projects. They are based on `ubuntu` images with Vapor's additional dependencies installed. These images assume you will copy over Swift's runtime libraries from the build container.

---

<div class="post-metadata">

**Author:** ![Optional](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/optional/32/12543_2.png) [@Optional](https://forums.swift.org/u/Optional)\
**Post date:** [December 19, 2019, 12:53am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/2 "2019-12-19T00:53:31Z")

</div>

I think the document needs to be improved. 😄 😄

---

<div class="post-metadata">

**Author:** ![jarod](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jarod/32/364_2.png) [@jarod](https://forums.swift.org/u/jarod)\
**Post date:** [December 19, 2019, 3:03am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/3 "2019-12-19T03:03:29Z")

</div>

There's a lot of great stuff here, amazing work! I'm excited to try it out!

---

<div class="post-metadata">

**Author:** ![rlziii](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rlziii/32/12167_2.png) [@rlziii](https://forums.swift.org/u/rlziii)\
**Post date:** [December 19, 2019, 3:53am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/4 "2019-12-19T03:53:31Z")

</div>

Great work! Very much looking forward to updating my current Vapor 3 applications to use Vapor 4's new features. I always enjoy reading about quality updates to server-side Swift web frameworks; I think the language fits well for this kind of application. I'm especially excited to see how `OpenCrypto` works out as I have been using `CryptoKit` for a personal project that also has a Vapor backend.

Glad to see that Vapor is still a healthy open-source project. 👍

---

<div class="post-metadata">

**Author:** ![Bruno](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bruno/32/7048_2.png) [@Bruno](https://forums.swift.org/u/Bruno)\
**Post date:** [December 19, 2019, 10:12am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/5 "2019-12-19T10:12:04Z")

</div>

Impressive amount of features 👏 👏 👏

Congratulations to all the Vapor team, now that Kitura is gone we need more projects that keep up with the delivery rate you are always having.

---

<div class="post-metadata">

**Author:** ![Corbilo](https://avatars.discourse-cdn.com/v4/letter/c/dec6dc/32.png) [@Corbilo](https://forums.swift.org/u/Corbilo)\
**Post date:** [December 19, 2019, 11:07am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/6 "2019-12-19T11:07:16Z")

</div>

_ **la critique est aisée, mais l’art est difficile** _

---

<div class="post-metadata">

**Author:** ![popaaaandrei](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/popaaaandrei/32/8474_2.png) [@popaaaandrei](https://forums.swift.org/u/popaaaandrei)\
**Post date:** [December 19, 2019, 2:01pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/7 "2019-12-19T14:01:10Z")

</div>

Great work guys! Really eager to test it in production 🙂  
Are there any improvements in performance?

---

<div class="post-metadata">

**Author:** ![twof](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/twof/32/1628_2.png) [@twof](https://forums.swift.org/u/twof)\
**Post date:** [December 19, 2019, 4:22pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/8 "2019-12-19T16:22:20Z")

</div>

I can't speak for the whole framework, you'll probably have to wait for the official TechEmpower benchmarks for that, but we made some significant improvements to the underlying router.

[https://github.com/vapor/routing-kit/pull/59](https://github.com/vapor/routing-kit/pull/59)

It's a little bit janky at the moment, but we also started performance testing incoming PRs.

[https://github.com/vapor/routing-kit/pull/66#issuecomment-466720351](https://github.com/vapor/routing-kit/pull/66#issuecomment-466720351)

Swift NIO also started performance testing PRs in this last cycle.

[https://github.com/apple/swift-nio/pull/1164#issuecomment-541827104](https://github.com/apple/swift-nio/pull/1164#issuecomment-541827104)

---

<div class="post-metadata">

**Author:** ![gpmake](https://avatars.discourse-cdn.com/v4/letter/g/a698b9/32.png) [@gpmake](https://forums.swift.org/u/gpmake)\
**Post date:** [December 19, 2019, 11:21pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/9 "2019-12-19T23:21:16Z")

</div>

This is a really important update! Great job! Congratulations Tanner and also to the whole project team!

---

<div class="post-metadata">

**Author:** ![li625317534](https://avatars.discourse-cdn.com/v4/letter/l/a698b9/32.png) [@li625317534](https://forums.swift.org/u/li625317534)\
**Post date:** [December 20, 2019, 6:46pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/10 "2019-12-20T18:46:42Z")

</div>

I want to add a timed task to the interface, but I don't know how to do it. I see that the function jobs is provided, can you provide a complete use case?

---

<div class="post-metadata">

**Author:** ![jordanebelanger](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jordanebelanger/32/13755_2.png) [@jordanebelanger](https://forums.swift.org/u/jordanebelanger)\
**Post date:** [December 24, 2019, 2:12pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/11 "2019-12-24T14:12:27Z")

</div>

Vapor 3 was already great but the tooling was a bit lacking.

Vapor 4 with all these nice upgrades is fantastic, and finally spm integration in xcode has made things much nicer overall.

Hopefully the documentation starts taking shape and more people can enjoy it very soon.

---

<div class="post-metadata">

**Author:** ![hlane](https://avatars.discourse-cdn.com/v4/letter/h/7c8e57/32.png) [@hlane](https://forums.swift.org/u/hlane)\
**Post date:** [January 1, 2020, 12:57am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/12 "2020-01-01T00:57:34Z")

</div>

Very cool stuff! I am particularly interested in the Jobs API, as there are definitely a few times I would have found such support quite useful. Its good to see this project keep gaining useful additions. Congrats to the whole Vapor team!

---

<div class="post-metadata">

**Author:** ![jcnm](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jcnm/32/2308_2.png) [@jcnm](https://forums.swift.org/u/jcnm)\
**Post date:** [January 6, 2020, 11:47pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/13 "2020-01-06T23:47:58Z")

</div>

Love these features, mostly the config, jobs and the eager loading ones!

Is there a way to change the default primary key to a precise one to lookup data using an alternative unique key when we are loading data by combining parameter member request and a given type ?

```
final class Galaxy: Model {
@ID(key: "id")
var id: UUID?

//additionnal tag 
@LOOKUP(key: "ref") // works just as an id
var ref: String?

@Field(key: "name")
var name: String
}

/// In the controller route:
route.get(path, Galaxy.parameter, gController.show)

/// in gController.show:
req.parameters.next(Galaxy. **self** ) // will retrieve the data looking up through ref and not the ID.
}

```

This feature could be usefull to use readable identifiers in the url without bouleplat additioning source code.

---

<div class="post-metadata">

**Author:** ![Jinxiansen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jinxiansen/32/10103_2.png) [@Jinxiansen](https://forums.swift.org/u/Jinxiansen)\
**Post date:** [January 7, 2020, 6:47pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/14 "2020-01-07T18:47:12Z")

</div>

Wow~ 2020.2

---

<div class="post-metadata">

**Author:** ![yasinkbas](https://avatars.discourse-cdn.com/v4/letter/y/db5fbb/32.png) [@yasinkbas](https://forums.swift.org/u/yasinkbas)\
**Post date:** [April 8, 2020, 2:30am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/15 "2020-04-08T02:30:25Z")

</div>

it's amazing stuff. Thanks, i now prefer you over django

---

<div class="post-metadata">

**Author:** ![t2davis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/t2davis/32/11329_2.png) [@t2davis](https://forums.swift.org/u/t2davis)\
**Post date:** [April 20, 2020, 5:43am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/16 "2020-04-20T05:43:33Z")

</div>

Yesss, all of this work is appreciated. Love the new jobs queuing system and the APNS package! Great work.

---

<div class="post-metadata">

**Author:** ![Max\_Howell1](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_howell1/32/10049_2.png) [@Max\_Howell1](https://forums.swift.org/u/Max_Howell1)\
**Post date:** [April 22, 2020, 9:14pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/17 "2020-04-22T21:14:55Z")

</div>

In fact to set the port is this code:

```swift
app.http.server.configuration.port = 8080

```

---

<div class="post-metadata">

**Author:** ![LucaMahler](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lucamahler/32/20404_2.png) [@LucaMahler](https://forums.swift.org/u/LucaMahler)\
**Post date:** [January 23, 2021, 11:36pm UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/18 "2021-01-23T23:36:14Z")

</div>

Sorry for the maybe stupid question, but how do you actually use Dependency Injection in Vapor 4?

For instance when using the MongoClient with a custom defined protocol as Repository abstraction?

How can I let these protocols be injected to constructors? How can I glue protocols to implementations?

---

<div class="post-metadata">

**Author:** ![knight2010](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/knight2010/32/20002_2.png) [@knight2010](https://forums.swift.org/u/knight2010)\
**Post date:** [December 10, 2021, 4:31am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/19 "2021-12-10T04:31:27Z")

</div>

Awesome, it should be helpful.

---

<div class="post-metadata">

**Author:** ![knight2010](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/knight2010/32/20002_2.png) [@knight2010](https://forums.swift.org/u/knight2010)\
**Post date:** [December 10, 2021, 4:33am UTC](https://forums.swift.org/t/whats-new-in-vapor-4/31832/20 "2021-12-10T04:33:04Z")

</div>

When will update to vapor 5

[Next page](https://forums.swift.org/t/whats-new-in-vapor-4/31832.md?page=2)
