Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ jobs:
linux_6_1_enabled: false
linux_6_2_enabled: false
linux_6_3_enabled: false
# linux_6_3_arguments_override: "-Xswiftc -warnings-as-errors --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_nightly_next_enabled: true
linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable"
linux_env_vars: '{"SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA":"1", "ENABLE_ALL_TRAITS":"1"}'

static-sdk:
name: Static SDK
uses: apple/swift-nio/.github/workflows/static_sdk.yml@main
with:
env_vars: '{"SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA":"1", "ENABLE_ALL_TRAITS":"1"}'

release-builds:
name: Release builds
Expand All @@ -38,3 +40,4 @@ jobs:
linux_6_2_enabled: false
linux_6_3_enabled: false
linux_nightly_next_enabled: true
linux_env_vars: '{"SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA":"1", "ENABLE_ALL_TRAITS":"1"}'
8 changes: 7 additions & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ on:
jobs:
soundness:
name: Soundness
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@0.0.11
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@497d9ab8410e69981b3b2f28da24cf7bf4b8733d
with:
api_breakage_check_container_image: "swiftlang/swift:nightly-6.4.x-noble"
format_check_container_image: "swiftlang/swift:nightly-6.4.x-noble"
license_header_check_project_name: "Swift HTTP Server"
linux_pre_build_command: "export SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA=1 ENABLE_ALL_TRAITS=1"

unit-tests:
name: Unit tests
Expand All @@ -29,6 +30,7 @@ jobs:
linux_nightly_next_enabled: true
linux_nightly_next_arguments_override: "--explicit-target-dependency-import-check error"
linux_nightly_main_arguments_override: "--explicit-target-dependency-import-check error"
linux_env_vars: '{"SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA":"1", "ENABLE_ALL_TRAITS":"1"}'

cxx-interop:
name: Cxx interop
Expand All @@ -40,10 +42,13 @@ jobs:
linux_6_2_enabled: false
linux_6_3_enabled: false
linux_nightly_next_enabled: true
linux_env_vars: '{"SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA":"1", "ENABLE_ALL_TRAITS":"1"}'

static-sdk:
name: Static SDK
uses: apple/swift-nio/.github/workflows/static_sdk.yml@main
with:
env_vars: '{"SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA":"1", "ENABLE_ALL_TRAITS":"1"}'

release-builds:
name: Release builds
Expand All @@ -55,3 +60,4 @@ jobs:
linux_6_2_enabled: false
linux_6_3_enabled: false
linux_nightly_next_enabled: false # should be disabled until next is 6.4
linux_env_vars: '{"SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA":"1", "ENABLE_ALL_TRAITS":"1"}'
61 changes: 56 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@

import PackageDescription

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif

let extraSettings: [SwiftSetting] = [
.strictMemorySafety(),
.enableExperimentalFeature("SuppressedAssociatedTypesWithDefaults"),
Expand All @@ -28,6 +34,44 @@ let extraSettings: [SwiftSetting] = [
.enableUpcomingFeature("InternalImportsByDefault"),
]

var traits: Set<Trait> = [
.trait(
name: "Configuration",
description: "Enables initializing NIOHTTPServerConfiguration from a swift-configuration ConfigProvider"
),
.trait(
name: "HTTP3",
description: "Enables HTTP/3 support"
),
]

let defaultTraits: Set<String> = ["Configuration"]

// Workaround to ensure that all traits are included in documentation. Swift Package Index adds SPI_GENERATE_DOCS
// (https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/2336) when building documentation, so only
// tweak the default traits in this condition.
let spiGenerateDocs = ProcessInfo.processInfo.environment["SPI_GENERATE_DOCS"] != nil

// Conditionally add the swift-docc plugin only when previewing docs locally.
// Preview with:
// ```
// SWIFT_PREVIEW_DOCS=1 swift package --disable-sandbox preview-documentation --target NIOHTTPServer
// ```
let previewDocs = ProcessInfo.processInfo.environment["SWIFT_PREVIEW_DOCS"] != nil

// Enable all traits for other CI actions.
let enableAllTraitsExplicit = ProcessInfo.processInfo.environment["ENABLE_ALL_TRAITS"] != nil

let enableAllTraits = spiGenerateDocs || previewDocs || enableAllTraitsExplicit
let addDoccPlugin = previewDocs || spiGenerateDocs
let enableAllCIFlags = enableAllTraitsExplicit

traits.insert(
.default(
enabledTraits: enableAllTraits ? Set(traits.map(\.name)) : defaultTraits
),
)

let package = Package(
name: "swift-http-server",
platforms: [ // TODO: Needed until https://github.com/swiftlang/swift/issues/89028 is fixed
Expand All @@ -43,19 +87,19 @@ let package = Package(
targets: ["NIOHTTPServer"]
)
],
traits: [
.trait(name: "Configuration"),
.default(enabledTraits: ["Configuration"]),
],
traits: traits,
dependencies: [
.package(
url: "https://github.com/apple/swift-http-api-proposal.git",
.upToNextMinor(from: "0.2.0")
),
.package(url: "https://github.com/apple/swift-distributed-tracing.git", from: "1.4.1"),
.package(url: "https://github.com/apple/swift-certificates.git", from: "1.19.1"),
.package(url: "https://github.com/apple/swift-certificates.git", from: "1.19.3"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.14.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.101.3"),
.package(url: "https://github.com/apple/swift-nio-quic.git", .upToNextMinor(from: "0.1.0")),
.package(url: "https://github.com/apple/swift-nio-quic-helpers.git", .upToNextMinor(from: "0.1.0")),
.package(url: "https://github.com/apple/swift-nio-http3.git", .upToNextMinor(from: "0.1.0")),
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.37.0"),
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.34.1"),
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.44.0"),
Expand Down Expand Up @@ -110,6 +154,13 @@ let package = Package(
condition: .when(traits: ["Configuration"])
),
.product(name: "NIOExtras", package: "swift-nio-extras"),
.product(name: "NIOQUIC", package: "swift-nio-quic", condition: .when(traits: ["HTTP3"])),
.product(
name: "NIOQUICHelpers",
package: "swift-nio-quic-helpers",
condition: .when(traits: ["HTTP3"])
),
.product(name: "NIOHTTP3", package: "swift-nio-http3", condition: .when(traits: ["HTTP3"])),
.product(name: "HTTPAPIs", package: "swift-http-api-proposal"),
],
swiftSettings: extraSettings
Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,24 @@ This package offers additional integrations you can enable using
Available traits:
- **`Configuration`** (default): Enables initializing `NIOHTTPServerConfiguration` from a `swift-configuration`
`ConfigProvider`.
- **`HTTP3`**: Enables HTTP/3 support.

## HTTP/3 support

Packages in the dependency tree depend on a beta release of swift-crypto.
Set the environment variable
`SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA` to allow swift-certificates
(in the dependency tree) to adopt swift-crypto beta releases as well.

```
SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA=1 swift build
```

To run all unit tests, run

```
SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA=1 swift test
```

Use `SWIFT_CERTIFICATES_ALLOW_SWIFT_CRYPTO_BETA=1 xed Package.swift` to open
the project in Xcode with the environment variable set.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct ConnectionHandlerExample {
// handler and the request handler are inline closures.
try await server.serve { connection, context in
var connection = Optional(connection)
try await withLogger(mergingMetadata: [
await withLogger(mergingMetadata: [
"peer": .string(context.remoteAddress.map { "\($0)" } ?? "unknown"),
"http": .string(context.httpVersion.rawValue),
]) { connectionLogger in
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift HTTP Server open source project
//
// Copyright (c) 2026 Apple Inc. and the Swift HTTP Server project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift HTTP Server project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

#if HTTP3
import HTTP3

@available(anyAppleOS 26.0, *)
extension NIOHTTPServerConfiguration.HTTP3 {
/// HTTP/3 connection settings sent to the peer during connection establishment.
public struct ConnectionSettings: Sendable, Hashable {
/// The maximum capacity of the QPACK dynamic table.
///
/// - SeeAlso: https://www.rfc-editor.org/rfc/rfc9204.html#section-5-2.2.1. Corresponds to
/// `SETTINGS_QPACK_MAX_TABLE_CAPACITY`.
public var qpackMaximumTableCapacity: UInt64

/// The maximum number of streams which may be blocked on QPACK at any one time.
///
/// - SeeAlso: https://www.rfc-editor.org/rfc/rfc9204.html#section-5-2.4.1. Corresponds to
/// `SETTINGS_QPACK_BLOCKED_STREAMS`.
public var qpackBlockedStreams: UInt64

/// The maximum size of a field section.
///
/// - SeeAlso: https://www.rfc-editor.org/rfc/rfc9114.html#section-7.2.4.1-2.2.1. Corresponds to
/// `SETTINGS_MAX_FIELD_SECTION_SIZE`.
public var maximumFieldSectionSize: UInt64?

/// The default HTTP/3 connection settings configuration.
///
/// Uses the following default values:
/// - `qpackMaximumTableCapacity`: 0.
/// - `qpackBlockedStreams`: 0.
/// - `maximumFieldSectionSize`: `nil` (no field section size limit).
public static var defaults: Self {
Self(
qpackMaximumTableCapacity: 0,
qpackBlockedStreams: 0,
maximumFieldSectionSize: nil
)
}
}
}

@available(anyAppleOS 26.0, *)
extension HTTP3.HTTP3Settings {
init(_ configuration: NIOHTTPServerConfiguration.HTTP3.ConnectionSettings) {
self.init(
qpackMaximumTableCapacity: configuration.qpackMaximumTableCapacity,
qpackBlockedStreams: configuration.qpackBlockedStreams,
maximumFieldSectionSize: configuration.maximumFieldSectionSize
)
}
}
#endif // HTTP3
Loading
Loading