diff --git a/Package.swift b/Package.swift index be6d235..1f27f53 100644 --- a/Package.swift +++ b/Package.swift @@ -60,10 +60,10 @@ let package = Package( .package(url: "https://github.com/apple/swift-distributed-tracing.git", from: "1.0.0"), .package(url: "https://github.com/apple/swift-certificates.git", from: "1.16.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"), - .package(url: "https://github.com/apple/swift-nio.git", from: "2.92.2"), + .package(url: "https://github.com/apple/swift-nio.git", from: "2.100.0"), .package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.36.0"), .package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.30.0"), - .package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.40.0"), + .package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.44.0"), .package(url: "https://github.com/apple/swift-configuration.git", from: "1.0.0"), .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.10.0"), ], @@ -90,6 +90,7 @@ let package = Package( .product(name: "NIOPosix", package: "swift-nio"), .product(name: "NIOHTTP1", package: "swift-nio"), .product(name: "NIOHTTP2", package: "swift-nio-http2"), + .product(name: "NIOHPACK", package: "swift-nio-http2"), .product(name: "NIOSSL", package: "swift-nio-ssl"), .product(name: "Logging", package: "swift-log"), .product(name: "NIOHTTPTypesHTTP1", package: "swift-nio-extras"), diff --git a/Sources/NIOHTTPServer/Configuration/NIOHTTPServer+SwiftConfiguration.swift b/Sources/NIOHTTPServer/Configuration/NIOHTTPServer+SwiftConfiguration.swift index 11dcdbb..ce55ff8 100644 --- a/Sources/NIOHTTPServer/Configuration/NIOHTTPServer+SwiftConfiguration.swift +++ b/Sources/NIOHTTPServer/Configuration/NIOHTTPServer+SwiftConfiguration.swift @@ -395,7 +395,7 @@ extension NIOHTTPServerConfiguration.HTTP2 { /// - `maxFrameSize` (int, optional, default: 2^14): The maximum frame size to be used in an HTTP/2 connection. /// - `targetWindowSize` (int, optional, default: 2^16 - 1): The target window size to be used in an HTTP/2 /// connection. - /// - `maxConcurrentStreams` (int, optional, default: nil): The maximum number of concurrent streams in an HTTP/2 + /// - `maxConcurrentStreams` (int, optional, default: 100): The maximum number of concurrent streams in an HTTP/2 /// connection. /// - `gracefulShutdown.maximumDuration` (int, optional, default: nil): The maximum amount of time (in seconds) that /// the connection has to close gracefully. @@ -411,10 +411,7 @@ extension NIOHTTPServerConfiguration.HTTP2 { forKey: "targetWindowSize", default: NIOHTTPServerConfiguration.HTTP2.defaultTargetWindowSize ), - /// The default value, ``NIOHTTPServerConfiguration.HTTP2.DEFAULT_TARGET_WINDOW_SIZE``, is `nil`. However, - /// we can only specify a non-nil `default` argument to `config.int(...)`. But `config.int(...)` already - /// defaults to `nil` if it can't find the `"maxConcurrentStreams"` key, so that works for us. - maxConcurrentStreams: config.int(forKey: "maxConcurrentStreams"), + maxConcurrentStreams: config.int(forKey: "maxConcurrentStreams", default: 100), gracefulShutdown: .init(config: config.scoped(to: "gracefulShutdown")) ) } diff --git a/Sources/NIOHTTPServer/Configuration/NIOHTTPServerConfiguration.swift b/Sources/NIOHTTPServer/Configuration/NIOHTTPServerConfiguration.swift index d2c7f56..5cf6e05 100644 --- a/Sources/NIOHTTPServer/Configuration/NIOHTTPServerConfiguration.swift +++ b/Sources/NIOHTTPServer/Configuration/NIOHTTPServerConfiguration.swift @@ -131,7 +131,7 @@ public struct NIOHTTPServerConfiguration: Sendable { public var targetWindowSize: Int /// The number of concurrent streams on the HTTP/2 connection. - public var maxConcurrentStreams: Int? + public var maxConcurrentStreams: Int /// The graceful shutdown configuration. public var gracefulShutdown: GracefulShutdownConfiguration @@ -162,7 +162,7 @@ public struct NIOHTTPServerConfiguration: Sendable { public init( maxFrameSize: Int = Self.defaultMaxFrameSize, targetWindowSize: Int = Self.defaultTargetWindowSize, - maxConcurrentStreams: Int? = Self.defaultMaxConcurrentStreams, + maxConcurrentStreams: Int = Self.defaultMaxConcurrentStreams, gracefulShutdown: GracefulShutdownConfiguration = .init() ) { self.maxFrameSize = maxFrameSize @@ -178,10 +178,10 @@ public struct NIOHTTPServerConfiguration: Sendable { static var defaultTargetWindowSize: Int { (1 << 16) - 1 } @inlinable - static var defaultMaxConcurrentStreams: Int? { nil } + static var defaultMaxConcurrentStreams: Int { 100 } - /// Default values. The max frame size defaults to 2^14, the target window size defaults to 2^16-1, and - /// the max concurrent streams default to infinite. + /// Default values. The max frame size defaults to 2^14, the target window size defaults to 2^16-1, and the max + /// concurrent streams default to 100. public static var defaults: Self { Self( maxFrameSize: Self.defaultMaxFrameSize, diff --git a/Sources/NIOHTTPServer/Documentation.docc/SwiftConfigurationIntegration.md b/Sources/NIOHTTPServer/Documentation.docc/SwiftConfigurationIntegration.md index 5cbcb7b..772ca54 100644 --- a/Sources/NIOHTTPServer/Documentation.docc/SwiftConfigurationIntegration.md +++ b/Sources/NIOHTTPServer/Documentation.docc/SwiftConfigurationIntegration.md @@ -47,7 +47,7 @@ respective key prefix. | `http` | `versions` | `string array` | Required (permitted values: `"http1_1"`, `"http2"`) | - | | `http.http2` | `maxFrameSize` | `int` | Optional | 2^14 | | | `targetWindowSize` | `int` | Optional | 2^16-1 | -| | `maxConcurrentStreams` | `int` | Optional | nil | +| | `maxConcurrentStreams` | `int` | Optional | 100 | | `http.http2.gracefulShutdown` | `maximumDuration` | `int` | Optional | nil | | `transportSecurity` | `mode` | `string` | Required (permitted values: `"plaintext"`, `"tls"`, `"mTLS"`) | - | | | `credentialSource` | `string` | Required for `"tls"` and `"mTLS"` (permitted values: `"inline"`, `"file"`) | - | @@ -95,7 +95,7 @@ key were omitted. "http2": { "maxFrameSize": 16384, // default: 2^14 (16384) "targetWindowSize": 65535, // default: 2^16 - 1 (65535) - "maxConcurrentStreams": 100, // default: nil (no limit) + "maxConcurrentStreams": 100, // default: 100 "gracefulShutdown": { "maximumDuration": 30 // default: nil (no time limit) } diff --git a/Sources/NIOHTTPServer/NIOHTTPServer.swift b/Sources/NIOHTTPServer/NIOHTTPServer.swift index cac5e8f..fd4f81e 100644 --- a/Sources/NIOHTTPServer/NIOHTTPServer.swift +++ b/Sources/NIOHTTPServer/NIOHTTPServer.swift @@ -19,6 +19,7 @@ import NIOCertificateReloading import NIOConcurrencyHelpers import NIOCore import NIOExtras +import NIOHPACK import NIOHTTP1 import NIOHTTP2 import NIOHTTPTypes @@ -337,15 +338,13 @@ extension NIOHTTP2Handler.Configuration { let clampedMaxFrameSize = Self.clampMaxFrameSize(http2Config.maxFrameSize) var http2HandlerConnectionConfiguration = NIOHTTP2Handler.ConnectionConfiguration() - var http2HandlerHTTP2Settings = HTTP2Settings([ + let http2HandlerHTTP2Settings = HTTP2Settings([ HTTP2Setting(parameter: .initialWindowSize, value: clampedTargetWindowSize), HTTP2Setting(parameter: .maxFrameSize, value: clampedMaxFrameSize), + HTTP2Setting(parameter: .maxConcurrentStreams, value: http2Config.maxConcurrentStreams), + HTTP2Setting(parameter: .maxHeaderListSize, value: HPACKDecoder.defaultMaxHeaderListSize), ]) - if let maxConcurrentStreams = http2Config.maxConcurrentStreams { - http2HandlerHTTP2Settings.append( - HTTP2Setting(parameter: .maxConcurrentStreams, value: maxConcurrentStreams) - ) - } + http2HandlerConnectionConfiguration.initialSettings = http2HandlerHTTP2Settings var http2HandlerStreamConfiguration = NIOHTTP2Handler.StreamConfiguration() diff --git a/Tests/NIOHTTPServerTests/NIOHTTPServerSwiftConfigurationTests.swift b/Tests/NIOHTTPServerTests/NIOHTTPServerSwiftConfigurationTests.swift index f910ce3..904f3b1 100644 --- a/Tests/NIOHTTPServerTests/NIOHTTPServerSwiftConfigurationTests.swift +++ b/Tests/NIOHTTPServerTests/NIOHTTPServerSwiftConfigurationTests.swift @@ -300,7 +300,7 @@ struct NIOHTTPServerSwiftConfigurationTests { #expect(http2.maxFrameSize == NIOHTTPServerConfiguration.HTTP2.defaultMaxFrameSize) #expect(http2.targetWindowSize == NIOHTTPServerConfiguration.HTTP2.defaultTargetWindowSize) - #expect(http2.maxConcurrentStreams == nil) + #expect(http2.maxConcurrentStreams == 100) #expect(http2.gracefulShutdown == .init(maximumGracefulShutdownDuration: nil)) } @@ -335,7 +335,7 @@ struct NIOHTTPServerSwiftConfigurationTests { #expect(http2.maxFrameSize == 5) #expect(http2.targetWindowSize == NIOHTTPServerConfiguration.HTTP2.defaultTargetWindowSize) - #expect(http2.maxConcurrentStreams == nil) + #expect(http2.maxConcurrentStreams == 100) #expect(http2.gracefulShutdown.maximumGracefulShutdownDuration == nil) } }