Skip to content

Commit

Permalink
Merge branch 'main' into keniwhat-merge
Browse files Browse the repository at this point in the history
* main:
  Patch configuration and log actual port on startup (vapor#3160)
  Update provider tests to 5.10 (vapor#3178)
  Migrate to Async NIOFileIO APIs (vapor#3167)
  Removed streamFile deprecation + deactivated advancedETagComparison by default (vapor#3177)
  Remove HeadResponder (vapor#3147)
  Advanced ETag Comparison now supported (vapor#3015)
  Enabled Request Decompression By Default (vapor#3175)
  HTTP2 Response Compression/Request Decompression (vapor#3126)
  Don't set ignore status for SIGTERM and SIGINT on Linux (vapor#3174)
  Fix typos across the codebase (vapor#3162)
  Fix some Sendable warnings on 5.10 (vapor#3158)
  Allow `HTTPServer`'s configuration to be dynamically updatable (vapor#3132)
  Fix issue when client disconnects midway through a stream (vapor#3102)
  Fix handling of "flag" URL query params (vapor#3151)
  Bump the dependencies group with 1 update (vapor#3148)
  Merge Async Tests (vapor#3141)
  Fix URI handling with multiple slashes and variable components. (vapor#3143)
  Fix broken URI behaviors (vapor#3140)

# Conflicts:
#	Package.swift
  • Loading branch information
Ken Carroll committed Apr 27, 2024
2 parents 94c7ea4 + e5cb0ab commit 79d0422
Show file tree
Hide file tree
Showing 75 changed files with 2,344 additions and 863 deletions.
2 changes: 1 addition & 1 deletion .github/contributing.md
Expand Up @@ -84,7 +84,7 @@ The release title should be concise description. For example:
- ✅ Add case-insensitive routing
- ✅ Fix `routes` command symbol usage

The release titles should use sentence capitialization and not be too verbose. They should also use present tense.
The release titles should use sentence capitalization and not be too verbose. They should also use present tense.

- ❌ Fix `routes` Command Symbol Usage
- ❌ Add new method on RouteBuilder called `caseInsensitive` which can be used to enable case-insensitive routing
Expand Down
2 changes: 1 addition & 1 deletion .github/maintainers.md
Expand Up @@ -6,7 +6,7 @@ maintainers will determine if you are a good fit and either accept and merge the
to be taken in order to be accepted.

## Perks
- Special "Maintainer" role in Discord with purple highlght.
- Special "Maintainer" role in Discord with purple highlight.
- Write access to maintained repo (including approve and merge permissions).
- Invite to "Maintainers" team on GitHub.
- Opportunity to actively participate in deciding on new features in package.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sponsors.yml
Expand Up @@ -26,7 +26,7 @@ jobs:
organization: true

- name: Commit and create PR
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
with:
token: ${{ steps.get-token.outputs.token }}
commit-message: "[skip ci] Update README with new sponsor"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Expand Up @@ -23,7 +23,7 @@ jobs:
- provider: vapor/apns
ref: 3.0.0
runs-on: ubuntu-latest
container: swift:5.9-jammy
container: swift:5.10
steps:
- name: Check out Vapor
uses: actions/checkout@v4
Expand Down
10 changes: 4 additions & 6 deletions Package.swift
Expand Up @@ -34,8 +34,8 @@ let package = Package(
.package(url: "https://github.com/swift-server/swift-backtrace.git", from: "1.1.1"),

// Event-driven network application framework for high performance protocol servers & clients, non-blocking.
.package(url: "https://github.com/apple/swift-nio.git", from: "2.62.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.63.0"),

// Bindings to OpenSSL-compatible libraries for TLS support in SwiftNIO
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.8.0"),

Expand Down Expand Up @@ -92,6 +92,8 @@ let package = Package(
.product(name: "WebSocketKit", package: "websocket-kit"),
.product(name: "MultipartKit", package: "multipart-kit"),
.product(name: "Atomics", package: "swift-atomics"),

.product(name: "_NIOFileSystem", package: "swift-nio"),
]),

// Development
Expand Down Expand Up @@ -120,9 +122,5 @@ let package = Package(
.copy("Utilities/expired.crt"),
.copy("Utilities/expired.key"),
]),
.testTarget(name: "AsyncTests", dependencies: [
.product(name: "NIOTestUtils", package: "swift-nio"),
.target(name: "XCTVapor"),
]),
]
)
15 changes: 3 additions & 12 deletions Package@swift-5.9.swift
Expand Up @@ -31,7 +31,7 @@ let package = Package(
.package(url: "https://github.com/vapor/routing-kit.git", from: "4.9.0"),

// Event-driven network application framework for high performance protocol servers & clients, non-blocking.
.package(url: "https://github.com/apple/swift-nio.git", from: "2.62.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.63.0"),

// Bindings to OpenSSL-compatible libraries for TLS support in SwiftNIO
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.8.0"),
Expand Down Expand Up @@ -90,6 +90,8 @@ let package = Package(
.product(name: "WebSocketKit", package: "websocket-kit"),
.product(name: "MultipartKit", package: "multipart-kit"),
.product(name: "Atomics", package: "swift-atomics"),

.product(name: "_NIOFileSystem", package: "swift-nio"),
],
swiftSettings: [.enableExperimentalFeature("StrictConcurrency=complete")]
),
Expand Down Expand Up @@ -133,16 +135,5 @@ let package = Package(
.enableExperimentalFeature("StrictConcurrency=complete"),
]
),
.testTarget(
name: "AsyncTests",
dependencies: [
.product(name: "NIOTestUtils", package: "swift-nio"),
.target(name: "XCTVapor"),
],
swiftSettings: [
.enableUpcomingFeature("BareSlashRegexLiterals"),
.enableExperimentalFeature("StrictConcurrency=complete"),
]
),
]
)
25 changes: 14 additions & 11 deletions README.md
Expand Up @@ -5,23 +5,26 @@
</a>

<p align="center">
<a href="https://docs.vapor.codes/4.0/">
<img src="http://img.shields.io/badge/read_the-docs-2196f3.svg" alt="Documentation">
<a href="https://docs.vapor.codes/4.0/">
<img src="https://design.vapor.codes/images/readthedocs.svg" alt="Documentation">
</a>
<a href="https://discord.gg/vapor">
<img src="https://img.shields.io/discord/431917998102675485.svg" alt="Team Chat">
<img src="https://design.vapor.codes/images/discordchat.svg" alt="Team Chat">
</a>
<a href="LICENSE">
<img src="https://img.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT License">
<img src="https://design.vapor.codes/images/mitlicense.svg" alt="MIT License">
</a>
<a href="https://github.com/vapor/vapor/actions">
<img src="https://github.com/vapor/vapor/actions/workflows/test.yml/badge.svg?branch=main" alt="Continuous Integration">
<a href="https://github.com/vapor/vapor/actions/workflows/test.yml">
<img src="https://img.shields.io/github/actions/workflow/status/vapor/vapor/test.yml?event=push&style=plastic&logo=github&label=tests&logoColor=%23ccc" alt="Continuous Integration">
</a>
<a href="https://codecov.io/gh/vapor/vapor">
<img src="https://img.shields.io/codecov/c/github/vapor/vapor?style=plastic&logo=codecov&label=codecov" alt="Code Coverage">
</a>
<a href="https://swift.org">
<img src="https://img.shields.io/badge/swift-5.7-brightgreen.svg" alt="Swift 5.7">
<img src="https://design.vapor.codes/images/swift57up.svg" alt="Swift 5.7+">
</a>
<a href="https://twitter.com/codevapor">
<img src="https://img.shields.io/badge/twitter-codevapor-5AA9E7.svg" alt="Twitter">
<a href="https://hachyderm.io/@codevapor">
<img src="https://img.shields.io/badge/%20-@codevapor-6364f6.svg?style=plastic&logo=mastodon&labelColor=gray&logoColor=%239394ff" alt="Mastodon">
</a>
</p>

Expand All @@ -33,11 +36,11 @@ Take a look at some of the [awesome stuff](https://github.com/Cellane/awesome-va

### 💧 Community

Join the welcoming community of fellow Vapor developers on [Discord](http://vapor.team).
Join the welcoming community of fellow Vapor developers on [Discord](https://vapor.team).

### 🚀 Contributing

To contribute a **feature or idea** to Vapor, [create an issue](https://github.com/vapor/vapor/issues/new) explaining your idea or bring it up on [Discord](http://vapor.team).
To contribute a **feature or idea** to Vapor, [create an issue](https://github.com/vapor/vapor/issues/new) explaining your idea or bring it up on [Discord](https://vapor.team).

If you find a **bug**, please [create an issue](https://github.com/vapor/vapor/issues/new).

Expand Down
2 changes: 1 addition & 1 deletion Sources/Vapor/Authentication/AuthenticationCache.swift
Expand Up @@ -104,7 +104,7 @@ extension Request.Authentication {
// multiple places. But given how Vapor and its users use Authentication this should almost never
// occur and it was decided the trade-off was acceptable
// As the name implies, the usage of this is unsafe because it disables the sendable checking of the
// compiler and does not add any synchronisation.
// compiler and does not add any synchronization.
@usableFromInline
internal struct UnsafeAuthenticationBox<A>: @unchecked Sendable {
@usableFromInline
Expand Down
6 changes: 5 additions & 1 deletion Sources/Vapor/Commands/ServeCommand.swift
Expand Up @@ -85,14 +85,18 @@ public final class ServeCommand: Command, Sendable {
// setup signal sources for shutdown
let signalQueue = DispatchQueue(label: "codes.vapor.server.shutdown")
func makeSignalSource(_ code: Int32) {
#if canImport(Darwin)
/// https://github.com/swift-server/swift-service-lifecycle/blob/main/Sources/UnixSignals/UnixSignalsSequence.swift#L77-L82
signal(code, SIG_IGN)
#endif

let source = DispatchSource.makeSignalSource(signal: code, queue: signalQueue)
source.setEventHandler {
print() // clear ^C
promise.succeed(())
}
source.resume()
box.signalSources.append(source)
signal(code, SIG_IGN)
}
makeSignalSource(SIGTERM)
makeSignalSource(SIGINT)
Expand Down
50 changes: 0 additions & 50 deletions Sources/Vapor/Concurrency/FileIO+Concurrency.swift

This file was deleted.

4 changes: 2 additions & 2 deletions Sources/Vapor/Concurrency/RequestBody+Concurrency.swift
Expand Up @@ -120,7 +120,7 @@ extension Request.Body: AsyncSequence {
/// Generates an `AsyncIterator` to stream the body’s content as
/// `ByteBuffer` sequences. This implementation supports backpressure using
/// `NIOAsyncSequenceProducerBackPressureStrategies`
/// - Returns: `AsyncIterator` containing the `Requeset.Body` as a
/// - Returns: `AsyncIterator` containing the `Request.Body` as a
/// `ByteBuffer` sequence
public func makeAsyncIterator() -> AsyncIterator {
let delegate = AsyncSequenceDelegate(eventLoop: request.eventLoop)
Expand Down Expand Up @@ -159,7 +159,7 @@ extension Request.Body: AsyncSequence {
// return the future that we will fulfill eventually.
return promise.futureResult
case .produceMore:
// We can produce more immidately. Return a succeeded future.
// We can produce more immediately. Return a succeeded future.
return request.eventLoop.makeSucceededVoidFuture()
}
case .error(let error):
Expand Down
14 changes: 11 additions & 3 deletions Sources/Vapor/Content/ContainerGetPathExecutor.swift
Expand Up @@ -2,7 +2,7 @@
internal struct ContainerGetPathExecutor<D: Decodable>: Decodable {
let result: D

static func userInfo(for keyPath: [CodingKey]) -> [CodingUserInfoKey: Any] {
static func userInfo(for keyPath: [CodingKey]) -> [CodingUserInfoKey: Sendable] {
[.containerGetKeypath: keyPath]
}

Expand All @@ -11,13 +11,21 @@ internal struct ContainerGetPathExecutor<D: Decodable>: Decodable {
throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Container getter couldn't find keypath to fetch (broken Decoder?)"))
}

self.result = try keypath.reduce(decoder) {
let lastDecoder = try keypath.dropLast().reduce(decoder) {
if let index = $1.intValue {
return try $0.unkeyedContainer(startingAt: index)._unsafe_inplace_superDecoder()
} else {
return try $0.container(keyedBy: BasicCodingKey.self).superDecoder(forKey: .key($1.stringValue))
}
}.singleValueContainer().decode(D.self)
}
if let index = keypath.last?.intValue {
var container = try lastDecoder.unkeyedContainer(startingAt: index)
self.result = try container.decode(D.self)
} else if let key = keypath.last?.stringValue {
self.result = try lastDecoder.container(keyedBy: BasicCodingKey.self).decode(D.self, forKey: .key(key))
} else {
self.result = try lastDecoder.singleValueContainer().decode(D.self)
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions Sources/Vapor/Content/ContentCoders.swift
Expand Up @@ -21,13 +21,13 @@ public protocol ContentEncoder {
///
/// For legacy API compatibility reasons, the default protocol conformance for this method forwards it to the legacy
/// encode method.
func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws
func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws
where E: Encodable
}

/// Conform a type to this protocol to make it usable for decoding data via Vapor's ``ContentConfiguration`` system.
public protocol ContentDecoder {
/// Legacy "decode object" method. The provided ``NIOCore/ByteBuffer`` should be decoded as a vaule of the given
/// Legacy "decode object" method. The provided ``NIOCore/ByteBuffer`` should be decoded as a value of the given
/// type, optionally guided by the provided ``NIOHTTP1/HTTPHeaders``.
///
/// Most decoders should implement this method by simply forwarding it to the decoder userInfo-aware version below,
Expand All @@ -36,26 +36,26 @@ public protocol ContentDecoder {
func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders) throws -> D
where D: Decodable

/// "Decode object" method. The provided ``NIOCore/ByteBuffer`` should be decoded as a vaule of the given type,
/// "Decode object" method. The provided ``NIOCore/ByteBuffer`` should be decoded as a value of the given type,
/// optionally guided by the provided ``NIOHTTP1/HTTPHeaders``. The provided ``userInfo`` dictionary must be
/// forwarded to the underlying ``Swift/Decoder`` used to perform the decoding operation.
///
/// For legacy API compatibility reasons, the default protocol conformance for this method forwards it to the legacy
/// decode method.
func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws -> D
func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws -> D
where D: Decodable
}

extension ContentEncoder {
public func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws
public func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws
where E: Encodable
{
try self.encode(encodable, to: &body, headers: &headers)
}
}

extension ContentDecoder {
public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws -> D
public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws -> D
where D: Decodable
{
try self.decode(decodable, from: body, headers: headers)
Expand Down
4 changes: 2 additions & 2 deletions Sources/Vapor/Content/ContentContainer.swift
Expand Up @@ -131,12 +131,12 @@ extension ContentContainer {

/// Injects coder userInfo into a ``ContentDecoder`` so we don't have to add passthroughs to ``ContentContainer``.
fileprivate struct ForwardingContentDecoder: ContentDecoder {
let base: ContentDecoder, info: [CodingUserInfoKey: Any]
let base: ContentDecoder, info: [CodingUserInfoKey: Sendable]

func decode<D: Decodable>(_: D.Type, from body: ByteBuffer, headers: HTTPHeaders) throws -> D {
try self.base.decode(D.self, from: body, headers: headers, userInfo: self.info)
}
func decode<D: Decodable>(_: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws -> D {
func decode<D: Decodable>(_: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws -> D {
try self.base.decode(D.self, from: body, headers: headers, userInfo: userInfo.merging(self.info) { $1 })
}
}
4 changes: 2 additions & 2 deletions Sources/Vapor/Content/JSONCoders+Content.swift
Expand Up @@ -9,7 +9,7 @@ extension JSONEncoder: ContentEncoder {
try self.encode(encodable, to: &body, headers: &headers, userInfo: [:])
}

public func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws
public func encode<E>(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws
where E: Encodable
{
headers.contentType = .json
Expand All @@ -36,7 +36,7 @@ extension JSONDecoder: ContentDecoder {
try self.decode(D.self, from: body, headers: headers, userInfo: [:])
}

public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws -> D
public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws -> D
where D: Decodable
{
let data = body.getData(at: body.readerIndex, length: body.readableBytes) ?? Data()
Expand Down
4 changes: 2 additions & 2 deletions Sources/Vapor/Content/PlaintextDecoder.swift
Expand Up @@ -13,7 +13,7 @@ public struct PlaintextDecoder: ContentDecoder {
}

/// `ContentDecoder` conformance.
public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Any]) throws -> D
public func decode<D>(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey: Sendable]) throws -> D
where D : Decodable
{
let string = body.getString(at: body.readerIndex, length: body.readableBytes)
Expand All @@ -29,7 +29,7 @@ private final class _PlaintextDecoder: Decoder, SingleValueDecodingContainer {
let userInfo: [CodingUserInfoKey: Any]
let plaintext: String?

init(plaintext: String?, userInfo: [CodingUserInfoKey: Any] = [:]) {
init(plaintext: String?, userInfo: [CodingUserInfoKey: Sendable] = [:]) {
self.plaintext = plaintext
self.userInfo = userInfo
}
Expand Down

0 comments on commit 79d0422

Please sign in to comment.