Swiftpack.co - Package - vapor/vapor

Documentation Team Chat MIT License Continuous Integration Swift 5.2 Twitter

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.

Take a look at some of the awesome stuff created with Vapor.

💧 Community

Join the welcoming community of fellow Vapor developers on Discord.

🚀 Contributing

To contribute a feature or idea to Vapor, create an issue explaining your idea or bring it up on Discord.

If you find a bug, please create an issue.

If you find a security vulnerability, please contact security@vapor.codes as soon as possible.

💛 Sponsors

Support Vapor's development by becoming a sponsor.

Nodes Skelpo Gwynne Raskind Autimatisering Kyle Browning Jari

💚 Backers

Support Vapor's development by becoming a backer.



Stars: 19032


Add Vapor 3 API shims - 2020-06-26 18:34:13

This patch was authored and released by @tanner0101.

Adds _Vapor3 module that contains deprecations for Vapor 3 APIs (#2373).

To use this module, add the product as a dependency to your App target in Package.swift. For example:

.target(name: "App", dependencies: [
    .product(name: "Vapor", package: "vapor"),
    .product(name: "_Vapor3", package: "vapor"),

Then import the _Vapor3 module to enable deprecations.

import Vapor
import _Vapor3


app.get("test") { req -> Future<String> in
//                       ^~~~~~
// 'Future' is deprecated: renamed to 'EventLoopFuture'

Note: This module only deprecates part of the Vapor 3 API. Some things are missing and not everything can be deprecated. If you'd like to add something, please open up a PR!

Immediate body streaming - 2020-06-26 18:25:26

This patch was authored and released by @tanner0101.

Refactors HTTP request body decoding to immediately make streaming bodies available via req.body.drain (#2413).

Previously, Vapor's HTTP request decoder would wait for a second body chunk to arrive before initiating body streaming. This was done as a performance optimization for single-chunk bodies since streaming has overhead. However, this behavior made it difficult to implement real time streaming handlers, like a ping/pong handler.

The HTTP request decoder has been updated to initiate body streaming immediately upon receiving the first chunk. To avoid impacting performance on small, non-streaming request bodies, a check for content-length has been added. If the request's body is contained entirely in a single chunk, streaming overhead is avoided.

Below are performance numbers on Ubuntu 20.04 in req/s.

|Method|Body Strategy|Previous|New|Delta| |-|-|-|-|-| |GET|.collect|229979.85|229333.16|0.28%| |POST|.collect|198949.90|196567.85|1.21%| |POST|.stream|197916.54|196178.48|0.89%|

The numbers show a negligible change in performance.

Logging improvements - 2020-06-26 16:59:36

This patch was authored and released by @tanner0101.

Improves readability of framework log messages and adds API for controlling error logging (#2412).

  • Downgraded several instances of .error level logging to .debug.

Note: The developer should have control over all .error level logs generated as the result of incoming HTTP requests.

  • Added logLevel property to DebuggableError.

Note: This allows DebuggableError's to control how they are reported to logs. Vapor's default "route not found" error uses this new API to log at .debug level.

  • Fixed an issue causing stack traces to be included when logLevel > .trace.

Note: Stack traces were only meant to be reported at the .trace level as they generate significant output.

  • Error source information is no longer duplicated in logs.

Fix #file usage for 5.3 - 2020-06-25 20:24:42

This patch was authored and released by @tanner0101.

Fixes issue with previous #file warning fix in 4.10.1 that caused incorrect file paths to be passed (#2411).

Wrapping the default #file parameter in parentheses prevents it from forwarding to the call site. The parentheses must be added before passing to the methods accepting #filePath.

See new discussion of SE-0274 for more information.

Add case-insensitive routing - 2020-06-24 19:35:13

This patch was authored by @tdotclare and released by @tanner0101.

Allows configuring case-insensitive routing (#2354).

// Enables case-insensitive routing.
// Defaults to false.
app.routes.caseInsensitive = true

Fix `routes` command symbol usage - 2020-06-24 19:01:51

This patch was authored by @stevapple and released by @tanner0101.

Update routes command to keep consistency with symbols used by RoutingKit like *, :, etc (#2366).

Fix `routes` command symbol usage - 2020-06-24 19:01:51

This patch was authored by @stevapple and released by @tanner0101.

Update routes command to keep consistency with symbols used by RoutingKit like *, :, etc (#2366).

HTTP streaming improvements - 2020-06-24 18:36:30

This patch was authored and released by @tanner0101.

Improves HTTP request and response streaming (#2404).

  • Streaming request body skipping will only happen if the entire response has been sent before the user starts reading the request body (fixes #2393).

Note: Previously, streaming request bodies would be drained automatically by Vapor as soon as the response head was sent. This made it impossible to implement realtime streaming, like an echo server. With these changes, you have much more control over streaming HTTP while still preventing hanging if the request body is ignored entirely.

  • Response body stream now supports omitting the count parameter (fixes #2393).

Note: Previously streaming bodies required a count and would always set the content-length header. Now, setting a count of -1 indicates a stream with indeterminate length. -1 will be used if the stream count is omitted. This results in transfer-encoding: chunked being used automatically.

  • Response writer provides a better error message if stream is never ended (fixes #2390).

  • Fixes an issue causing EOF framing to result in promise leak (fixes #2391).

  • Response streams with determinate length that write too few or too many bytes will now result in an error (fixes #2392).

Follow the 'required' argument for nested validations - 2020-06-24 08:19:14

This patch was authored by @seeppp and released by @MrLotU.

Validations now follows required argument while validating nested validations.

If we add a validation step of a nested object, which is optional, the required flag would be set false.

validations.add("optionalNestedObject", required: false, B.validations)

Therefore, we are now able to have an object like this:

struct A: Codable {
    var name: String
    var optionalNestedObject: A?

extension A: Validatable {
    static func validations(_ validations: inout Validations) {
        validations.add("name", as: String.self, is: .ascii)
        validations.add("optionalNestedObject", required: false, A.validations)

The validator now validates the nested object only if optionalNestedObject != nil.

If the nested object is non-optional, you can still omit the required argument.

validations.add("nestedObject", B.validations)

Remove percent encoding when logging url path - 2020-06-24 08:01:26

This patch was authored by @valeriomazzeo and released by @MrLotU.

Remove percent encoding when logging url path (#2399)

The DefaultResponder now removes the percent encoding when logging the url request's path.

Previous log:

[ INFO ] GET /users/auth0%7C59abc/

After this change:

[ INFO ] GET /users/auth0|59abc/

Fix warnings in Xcode 12 - 2020-06-23 18:37:24

This patch was authored and released by @tanner0101.

Updates to remove warnings for Xcode 12 (#2405).

Abort and StackTrace improvements - 2020-06-15 22:58:55

This patch was authored and released by @tanner0101.

Abort now conforms to DebuggableError (#2400).

Abort now exposes source, reason, identifier, and stackTrace via the DebuggableError protocol.

⚠️ Abort.source is now an optional as required by DebuggableError.

Abort now captures StackTrace by default.

func foo() throws {
    try bar()
func bar() throws {
    try baz()
func baz() throws {
    throw Abort(.internalServerError, reason: "Oops")
do {
    try foo()
} catch let error as DebuggableError {
    XCTAssertContains(error.stackTrace?.frames[0].function, "baz")
    XCTAssertContains(error.stackTrace?.frames[1].function, "bar")
    XCTAssertContains(error.stackTrace?.frames[2].function, "foo")

To avoid capturing a stack trace, pass nil:

Abort(.internalServerError, reason: "Oops", stackTrace: nil)

To disable stack traces globally, use:

StackTrace.isCaptureEnabled = false

Improved StackTrace.capture on Linux (#2400).

StackTrace.capture on Linux now utilizes libbacktrace to provide symbol names.

0 VaporTests baz #1 () throws -> () in VaporTests.ErrorTests.testAbortDebuggable() throws -> ()
1 VaporTests bar #1 () throws -> () in VaporTests.ErrorTests.testAbortDebuggable() throws -> ()
2 VaporTests foo #1 () throws -> () in VaporTests.ErrorTests.testAbortDebuggable() throws -> ()
3 VaporTests VaporTests.ErrorTests.testAbortDebuggable() throws -> ()

StackFrame.capture now accepts an optional skip parameter. Use this to exclude any extraneous stack frames from the captured result.

// Captures stack trace, excluding this init call.
init(stackTrace: StackTrace? = .capture(skip: 1)) {

Rename CORSMiddleware allowable origins case - 2020-06-13 02:29:17

This patch was authored and released by @tanner0101.

Renames CORSMiddleware.AllowOriginSetting's list of allowable origins case to .any (#2397).

Add support for PartialRangeUpTo in validators - 2020-06-01 21:19:22

This patch was authored by @adtrevor and released by @gwynne.

Up until right now, the .count(...) and .range(...) validators didn't support being passed a PartialRangeUpTo. This commit adds support for this.

This also improves and fixes documentation

Support periods in cookie names - 2020-05-28 16:28:26

This patch was authored and released by @tanner0101.

Adds support for . in HTTP header value directive keys, like cookie names (#2372, fixes #2359).

Refactor request body streaming state handling - 2020-05-27 19:37:18

This patch was authored and released by @tanner0101.
  • Implements new state machine for handling streaming request bodies (#2357).

This new state machine ensures that calls to req.body.drain will only ever happen after the previously returned future has completed. This makes it easier to correctly implement streaming file writes. Addresses https://forums.swift.org/t/how-to-use-nonblockingfileio-for-repeated-writes/36206.

  • Request bodies are now automatically drained after sending a response (#2357, fixes #2356).

This change ensures that streaming requests will be read completely even if a route ignores their body.

  • Adds a streaming file upload example to the Development executable (#2357).

  • Improves BodyStreamResult's normal and debug descriptions (#2357).

  • Fixed a reference cycle if Request was captured strongly within the body.drain closure (#2357).

`Environment` cleanups - 2020-05-26 17:27:32

This patch was authored and released by @gwynne.
  • Clean up Environment's implementation.

  • Add the ability to specify the application environment using the environment variable VAPOR_ENV (partial implementation of #2333). If both VAPOR_ENV and --env are provided, the latter always takes precedence.

  • Environment now recognizes and strips the spurious arguments Xcode passes to test runners when a scheme doesn't specify any arguments of its own. It will do this especially specifically for the testing environment, which is often explicitly specified to Application's initializers instead of .detect() in unit tests. This behavior is only enabled when building in Xcode or with xcodebuild. This negates the need to explicitly override the input arguments in the non-production presets, meaning command line arguments no longer occasionally seem to vanish into thin air in certain cases.

  • Redo the documentation comments for both versions of Environment.secret() and significantly simplify the implementation. Important: This is an interim cleanup step pending a complete revamp of the secret() API.

Note: Pains have been taken not to change the observable behavior of any public APIs and to remain otherwise behaviorally consistent. The addition of VAPOR_ENV counts as new public API and thus drives this being a semver-minor change, but in all other respects it should have no visible effect.

Fix invalid session ID handling - 2020-05-06 16:38:06

This patch was authored and released by @tanner0101.

Requests containing unrecognized session IDs will now result in a new session being created (#2347, fixes #2339).

This fixes a problem where clearing browser cookies would be required after changing Vapor's session driver.

Default max body size for streaming request body collection - 2020-05-01 20:39:09

This patch was authored by @calebkleveter and released by @tanner0101.

Adds app.routes.defaultMaxBodySize for configuring default maximum body size for streaming body collection (#2312).

A ByteCount type has been added for easily expressing byte counts as strings like "1mb", "200GB", or "42 kb". This type is now usable where maximum body size integers were previously accepted (#2312).

Vapor collects streaming bodies up to 16KB in size automatically before calling route closures. This makes it easier to decode content from requests since you can assume the entire request is already available in memory.

To increase the maximum allowable size for streaming body collection, you can pass an arbitrary maxSize to the collect case of the body parameter in RouteBuilder.on.

app.on(.POST, "upload", body: .collect(maxSize: "1mb")) { req in
    // Handle request. 

For more information on this API, visit https://docs.vapor.codes/4.0/routing/#body-streaming.

Now, in addition to setting this parameter for each route, you can change the global default Vapor uses.

app.routes.defaultMaxBodySize = "10mb"

Route specific maximum size will always take precedence over the application default.

Note: This maximum size only affects streaming request bodies. Non-streaming request bodies (request bodies that arrive in a single buffer from SwiftNIO) will not be subject to the maximum size restriction.

⚠️ Using .collect(maxSize: nil) will now result in the application's default maximum body size being used.

Use runIfActive instead of submit in async passwords - 2020-04-30 17:32:11

This patch was authored by @mcdappdev and released by @0xTim.

Replaces the use of threadPool.submit { _ in with threadPool.runIfActive as detailed in https://github.com/vapor/docs/pull/478

URLEncodedForm date encoding strategy - 2020-04-21 18:21:44

Adds ability to configure the date encoding and decoding strategy for the URLEncodedFormDecoder and URLEncodedFormEncoder (#2273).

HTTPMediaType comparisons should be case insensitive - 2020-04-21 16:26:57

This patch was authored and released by @grosch.

Updates HTTPMediaType equality checks so that the values are no longer case sensitive.

Fix CORSMiddleware configuration initializer parameter - 2020-04-17 15:18:46

This patch was authored by @grosch and released by @tanner0101.

Updates CORSMiddleware.Configuration's exposedHeaders parameter to accept [HTTPHeader.Name] instead of [String] like the other parameters do (#2314).

Support numbers in header directive keys - 2020-04-16 17:41:03

This patch was authored and released by @tanner0101.

HTTP header directive keys now support numbers. This fixes an issue with cookies not being parsed correctly when the key included a number in the name (#2317, fixes #2316).

Support numbers in header directive keys - 2020-04-16 17:41:03

This patch was authored and released by @tanner0101.

HTTP header directive keys now support numbers. This fixes an issue with cookies not being parsed correctly when the key included a number in the name (#2317, fixes #2316).

Add Content hooks - 2020-04-15 20:20:35

This patch was authored by @grosch and released by @tanner0101.

Adds optional beforeEncode and afterDecode methods to Content protocol (#2267).

Docs: https://docs.vapor.codes/4.0/content/#hooks

Make Request.route publicly settable - 2020-04-14 20:01:21

This patch was authored and released by @mcdappdev.

Makes Request.route publicly settable (#2315). This makes it easier to build and use custom Responder types.

Improve body handling for HEAD responses - 2020-04-14 18:16:09

This patch was authored and released by @tanner0101.

Improves logic for handling HEAD responses (#2310).

Previously when HEAD requests were detected, the response body would be replaced with an empty body and the content-length header would be re-added. This caused problems with responses that don't use the content-length header, even for non-HEAD requests.

Now, when HEAD requests are detected, the response body is not changed. Instead, a flag is set signaling the serializer to skip serialization of the body.

Change async password verifier to non-throwing - 2020-04-09 18:34:33

This patch was authored by @madsodgaard and released by @tanner0101.

Changed AsyncPasswordVerifier methods to be non-throwing, since it is async.

Vapor 4.0.0 - 2020-04-09 17:49:55

New Docs:

  • https://docs.vapor.codes/4.0/environment/
  • https://docs.vapor.codes/4.0/errors/
  • https://docs.vapor.codes/4.0/middleware/
  • https://docs.vapor.codes/4.0/testing/
  • https://docs.vapor.codes/4.0/server/
  • https://docs.vapor.codes/4.0/sessions/
  • https://docs.vapor.codes/4.0/services/
  • https://docs.vapor.codes/4.0/passwords/

More information on Vapor 4 official release: https://forums.swift.org/t/vapor-4-official-release-begins/34802

Changes since last pre-release. Breaking changes have a warning symbol.

  • ⚠️ Authenticators now return Void and have no associated User type.

Authenticators should now use req.auth.login internally to login the user instead of returning it. This change allows for authenticators to login one or more user types and prevents the need for associated types.

  • ⚠️ HTTP client and server configuration are now prefixed with app.http.
// Configure HTTP server.
app.http.server.configuration.hostname = ...

// Configure HTTP client.
app.http.client.configuration.followRedirects = ...
  • ⚠️ Shared HTTP client and server are now accessible via app.http.
print(app.http.client.shared) // AsyncHTTPClient.HTTPClient
  • Client is now configurable.
app.clients.use { app in
  • Server is now configurable.
app.servers.use { app in
  • New configurable password hashing API added.
let digest = try app.password.hash("vapor")
try app.password.verify("vapor", created: digest)

Async password hashing support included.

req.password.async.hash("vapor").map { digest in
    // Handle digest.
  • Unused HTTPServer configuration options were removed.

  • Tests have been broken out into separate files.