From 02669f9fd8022be8d6ac0f5d09f91d19f0a8b6d5 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Tue, 5 Aug 2025 13:53:00 +0100 Subject: [PATCH 1/4] Replace platforms with availability annotations --- Package.swift | 6 +----- Sources/Example/Example.swift | 2 ++ .../Example/Middlewares/HTTPRequestLoggingMiddleware.swift | 3 +++ Sources/Example/Middlewares/RouteHandlerMiddleware.swift | 1 + Sources/Example/Middlewares/TimeoutMiddleware.swift | 2 ++ Sources/Example/Middlewares/TracingMiddleware.swift | 1 + Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift | 2 ++ .../HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift | 2 ++ Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift | 1 + Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift | 1 + Sources/HTTPServer/HTTPServer.swift | 1 + Sources/HTTPServer/HTTPServerClosureRequestHandler.swift | 1 + Sources/HTTPServer/HTTPServerConfiguration.swift | 1 + Sources/HTTPServer/HTTPServerRequestHandler.swift | 1 + 14 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index 989bc2a..bb2b4cd 100644 --- a/Package.swift +++ b/Package.swift @@ -10,11 +10,7 @@ let extraSettings: [SwiftSetting] = [ .enableUpcomingFeature("InferIsolatedConformances"), .enableUpcomingFeature("ExistentialAny"), .enableUpcomingFeature("MemberImportVisibility"), - .enableUpcomingFeature("InternalImportsByDefault"), - .unsafeFlags([ - "-Xfrontend", - "-disable-availability-checking", - ]), + .enableUpcomingFeature("InternalImportsByDefault") ] let package = Package( diff --git a/Sources/Example/Example.swift b/Sources/Example/Example.swift index a3a2d5a..007a520 100644 --- a/Sources/Example/Example.swift +++ b/Sources/Example/Example.swift @@ -8,6 +8,7 @@ import Middleware import X509 @main +@available(macOS 26.0, *) struct Example { static func main() async throws { try await serve() @@ -68,6 +69,7 @@ struct Example { // MARK: - Server Extensions +@available(macOS 26.0, *) extension Server { /// Serve HTTP requests using a middleware chain built with the provided builder /// This method handles the type inference for HTTP middleware components diff --git a/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift b/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift index 30d604c..e1289e4 100644 --- a/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift +++ b/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift @@ -3,6 +3,7 @@ import HTTPTypes import Logging import Middleware +@available(macOS 26.0, *) struct HTTPRequestLoggingMiddleware< RequestConludingAsyncReader: ConcludingAsyncReader, ResponseConcludingAsyncWriter: ConcludingAsyncWriter & ~Copyable @@ -62,6 +63,7 @@ where } } +@available(macOS 26.0, *) struct HTTPRequestLoggingConcludingAsyncReader< Base: ConcludingAsyncReader >: ConcludingAsyncReader @@ -123,6 +125,7 @@ where } } +@available(macOS 26.0, *) struct HTTPResponseLoggingConcludingAsyncWriter< Base: ConcludingAsyncWriter & ~Copyable >: ConcludingAsyncWriter, ~Copyable diff --git a/Sources/Example/Middlewares/RouteHandlerMiddleware.swift b/Sources/Example/Middlewares/RouteHandlerMiddleware.swift index f6ac470..9b1f39d 100644 --- a/Sources/Example/Middlewares/RouteHandlerMiddleware.swift +++ b/Sources/Example/Middlewares/RouteHandlerMiddleware.swift @@ -2,6 +2,7 @@ import HTTPServer import HTTPTypes import Middleware +@available(macOS 26.0, *) struct RouteHandlerMiddleware< RequestConcludingAsyncReader: ConcludingAsyncReader & Copyable, ResponseConcludingAsyncWriter: ConcludingAsyncWriter & ~Copyable, diff --git a/Sources/Example/Middlewares/TimeoutMiddleware.swift b/Sources/Example/Middlewares/TimeoutMiddleware.swift index a946d7b..2dab27c 100644 --- a/Sources/Example/Middlewares/TimeoutMiddleware.swift +++ b/Sources/Example/Middlewares/TimeoutMiddleware.swift @@ -1,5 +1,6 @@ import Middleware +@available(macOS 26.0, *) struct TimeoutMiddleware: Middleware { func intercept(input: Input, next: (Input) async throws -> Void) async throws { try await withoutActuallyEscaping(next) { next in @@ -21,6 +22,7 @@ package struct TimeOutError: Error { var underlying: any Error } +@available(macOS 26.0, *) public func withTimeout( in timeout: Clock.Duration, clock: Clock, diff --git a/Sources/Example/Middlewares/TracingMiddleware.swift b/Sources/Example/Middlewares/TracingMiddleware.swift index a0c91b9..243828b 100644 --- a/Sources/Example/Middlewares/TracingMiddleware.swift +++ b/Sources/Example/Middlewares/TracingMiddleware.swift @@ -2,6 +2,7 @@ import HTTPTypes import Middleware import Tracing +@available(macOS 26.0, *) struct TracingMiddleware: Middleware { func intercept( input: Input, diff --git a/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift b/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift index 2084cef..27807ad 100644 --- a/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift +++ b/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift @@ -2,6 +2,7 @@ /// /// ``AsyncReader`` defines an interface for types that can asynchronously read elements /// of a specified type from a source. +@available(macOS 26.0, *) public protocol AsyncReader { /// The type of elements that can be read by this reader. associatedtype ReadElement: ~Copyable, ~Escapable @@ -44,6 +45,7 @@ public protocol AsyncReader { ) async throws(ReadFailure) -> Return } +@available(macOS 26.0, *) extension AsyncReader { /// Collects elements from the reader up to a specified limit and processes them with a body function. /// diff --git a/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift b/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift index 720de8b..3dfc896 100644 --- a/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift +++ b/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift @@ -4,6 +4,7 @@ /// provide a conclusive element after all reads are completed. This is particularly useful /// for streams that have meaningful completion states beyond just terminating, such as /// HTTP responses that include headers after the body is fully read. +@available(macOS 26.0, *) public protocol ConcludingAsyncReader { /// The underlying asynchronous reader type that produces elements. associatedtype Underlying: AsyncReader, ~Copyable, ~Escapable @@ -37,6 +38,7 @@ public protocol ConcludingAsyncReader { ) async throws -> (Return, FinalElement) } +@available(macOS 26.0, *) extension ConcludingAsyncReader { /// Processes the underlying async reader until completion and returns only the final element. /// diff --git a/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift b/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift index 77b3564..d5934ad 100644 --- a/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift +++ b/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift @@ -9,6 +9,7 @@ import NIOHTTPTypes /// and concluding with the HTTP trailer fields received at the end of the request. This type /// follows the ``ConcludingAsyncReader`` pattern, which allows for asynchronous consumption of /// a stream with a conclusive final element. +@available(macOS 26.0, *) public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader { /// A reader for HTTP request body chunks that implements the ``AsyncReader`` protocol. /// diff --git a/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift b/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift index 8f5c404..07d3766 100644 --- a/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift +++ b/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift @@ -11,6 +11,7 @@ import NIOHTTPTypes /// /// This writer is designed to work with HTTP responses where the body is streamed in chunks /// and potentially followed by trailer fields. +@available(macOS 26.0, *) public struct HTTPResponseConcludingAsyncWriter: ConcludingAsyncWriter, ~Copyable { /// A writer for HTTP response body chunks that implements the ``AsyncWriter`` protocol. /// diff --git a/Sources/HTTPServer/HTTPServer.swift b/Sources/HTTPServer/HTTPServer.swift index dddb3ca..e7eca05 100644 --- a/Sources/HTTPServer/HTTPServer.swift +++ b/Sources/HTTPServer/HTTPServer.swift @@ -59,6 +59,7 @@ import SwiftASN1 /// } /// } /// ``` +@available(macOS 26.0, *) public final class Server { /// Starts an HTTP server with a closure-based request handler. /// diff --git a/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift b/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift index 2d31023..02b2acc 100644 --- a/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift +++ b/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift @@ -23,6 +23,7 @@ public import HTTPTypes /// } /// } /// ``` +@available(macOS 26.0, *) public struct HTTPServerClosureRequestHandler: HTTPServerRequestHandler { /// The underlying closure that handles HTTP requests private let _handler: diff --git a/Sources/HTTPServer/HTTPServerConfiguration.swift b/Sources/HTTPServer/HTTPServerConfiguration.swift index 8fe9afa..7c45add 100644 --- a/Sources/HTTPServer/HTTPServerConfiguration.swift +++ b/Sources/HTTPServer/HTTPServerConfiguration.swift @@ -4,6 +4,7 @@ public import X509 /// /// This structure contains all the necessary configuration options for setting up /// and running an HTTP server, including network binding and TLS settings. +@available(macOS 26.0, *) public struct HTTPServerConfiguration: Sendable { /// Specifies where the server should bind and listen for incoming connections. /// diff --git a/Sources/HTTPServer/HTTPServerRequestHandler.swift b/Sources/HTTPServer/HTTPServerRequestHandler.swift index 2e2776a..5159250 100644 --- a/Sources/HTTPServer/HTTPServerRequestHandler.swift +++ b/Sources/HTTPServer/HTTPServerRequestHandler.swift @@ -53,6 +53,7 @@ public import HTTPTypes /// } /// } /// ``` +@available(macOS 26.0, *) public protocol HTTPServerRequestHandler: Sendable { /// Handles an incoming HTTP request and generates a response. /// From 9932e76de56eca8b10d97af51f8e9377f16b36cf Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Tue, 5 Aug 2025 16:00:52 +0100 Subject: [PATCH 2/4] Fix Sendability issue --- Sources/Example/Example.swift | 2 +- Sources/Middleware/ChainedMiddleware.swift | 2 +- Sources/Middleware/Middleware.swift | 4 ++-- Sources/Middleware/MiddlewareChain.swift | 14 ++++++++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Sources/Example/Example.swift b/Sources/Example/Example.swift index 007a520..534ecd6 100644 --- a/Sources/Example/Example.swift +++ b/Sources/Example/Example.swift @@ -86,7 +86,7 @@ extension Server { ) async throws -> HTTPResponseConcludingAsyncWriter ), Never - > & Sendable + > ) async throws where RequestHandler == HTTPServerClosureRequestHandler { let chain = middlewareBuilder() diff --git a/Sources/Middleware/ChainedMiddleware.swift b/Sources/Middleware/ChainedMiddleware.swift index 4f1096f..4fae280 100644 --- a/Sources/Middleware/ChainedMiddleware.swift +++ b/Sources/Middleware/ChainedMiddleware.swift @@ -34,7 +34,7 @@ struct ChainedMiddleware: Middleware { /// - Throws: Any error that occurs during processing in either middleware. func intercept( input: Input, - next: (NextInput) async throws -> Void + next: @Sendable (NextInput) async throws -> Void ) async throws { try await first.intercept(input: input) { middleInput in try await second.intercept(input: middleInput, next: next) diff --git a/Sources/Middleware/Middleware.swift b/Sources/Middleware/Middleware.swift index 585550d..bbecf82 100644 --- a/Sources/Middleware/Middleware.swift +++ b/Sources/Middleware/Middleware.swift @@ -9,7 +9,7 @@ /// /// - Note: Middleware components are designed to be composable. You can use the /// `MiddlewareChainBuilder` to easily construct middleware chains. -public protocol Middleware { +public protocol Middleware: Sendable { /// The input type that this middleware accepts. associatedtype Input @@ -30,6 +30,6 @@ public protocol Middleware { /// - Throws: Any error that occurs during processing. func intercept( input: Input, - next: (NextInput) async throws -> Void + next: @Sendable (NextInput) async throws -> Void ) async throws } diff --git a/Sources/Middleware/MiddlewareChain.swift b/Sources/Middleware/MiddlewareChain.swift index b215c3c..d7c711f 100644 --- a/Sources/Middleware/MiddlewareChain.swift +++ b/Sources/Middleware/MiddlewareChain.swift @@ -8,9 +8,9 @@ /// interface that can represent both simple and complex middleware arrangements. public struct MiddlewareChain: Middleware { private let middlewareFunc: - ( + @Sendable ( Input, - (NextInput) async throws -> Void + @Sendable (NextInput) async throws -> Void ) async throws -> Void /// Creates a new middleware chain from an existing middleware component. @@ -20,7 +20,9 @@ public struct MiddlewareChain: Middleware { /// /// - Parameter middleware: The middleware component to wrap in a chain. public init(middleware: some Middleware) { - self.middlewareFunc = middleware.intercept + self.middlewareFunc = { input, nextInput in + try await middleware.intercept(input: input, next: nextInput) + } } /// Creates a middleware chain using a raw middleware function. @@ -30,9 +32,9 @@ public struct MiddlewareChain: Middleware { /// /// - Parameter middlewareFunc: A closure that implements the middleware's behavior. init( - middlewareFunc: @escaping ( + middlewareFunc: @Sendable @escaping ( Input, - (NextInput) async throws -> Void + @Sendable (NextInput) async throws -> Void ) async throws -> Void ) { self.middlewareFunc = middlewareFunc @@ -51,7 +53,7 @@ public struct MiddlewareChain: Middleware { /// - Throws: Any error that occurs during processing. public func intercept( input: Input, - next: (NextInput) async throws -> Void + next: @Sendable (NextInput) async throws -> Void ) async throws { try await middlewareFunc(input, next) } From 0d69c59a07667f25e744f70d04bf3f3907e19b02 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Wed, 6 Aug 2025 13:08:57 +0100 Subject: [PATCH 3/4] Add all platforms --- Sources/Example/Example.swift | 4 ++-- .../Example/Middlewares/HTTPRequestLoggingMiddleware.swift | 6 +++--- Sources/Example/Middlewares/RouteHandlerMiddleware.swift | 2 +- Sources/Example/Middlewares/TimeoutMiddleware.swift | 4 ++-- Sources/Example/Middlewares/TracingMiddleware.swift | 2 +- Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift | 4 ++-- .../HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift | 4 ++-- Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift | 2 +- Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift | 2 +- Sources/HTTPServer/HTTPServer.swift | 2 +- Sources/HTTPServer/HTTPServerClosureRequestHandler.swift | 2 +- Sources/HTTPServer/HTTPServerConfiguration.swift | 2 +- Sources/HTTPServer/HTTPServerRequestHandler.swift | 2 +- Tests/HTTPServerTests/HTTPServerTests.swift | 2 +- 14 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Sources/Example/Example.swift b/Sources/Example/Example.swift index 534ecd6..92f6805 100644 --- a/Sources/Example/Example.swift +++ b/Sources/Example/Example.swift @@ -8,7 +8,7 @@ import Middleware import X509 @main -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) struct Example { static func main() async throws { try await serve() @@ -69,7 +69,7 @@ struct Example { // MARK: - Server Extensions -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) extension Server { /// Serve HTTP requests using a middleware chain built with the provided builder /// This method handles the type inference for HTTP middleware components diff --git a/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift b/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift index e1289e4..d82f236 100644 --- a/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift +++ b/Sources/Example/Middlewares/HTTPRequestLoggingMiddleware.swift @@ -3,7 +3,7 @@ import HTTPTypes import Logging import Middleware -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) struct HTTPRequestLoggingMiddleware< RequestConludingAsyncReader: ConcludingAsyncReader, ResponseConcludingAsyncWriter: ConcludingAsyncWriter & ~Copyable @@ -63,7 +63,7 @@ where } } -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) struct HTTPRequestLoggingConcludingAsyncReader< Base: ConcludingAsyncReader >: ConcludingAsyncReader @@ -125,7 +125,7 @@ where } } -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) struct HTTPResponseLoggingConcludingAsyncWriter< Base: ConcludingAsyncWriter & ~Copyable >: ConcludingAsyncWriter, ~Copyable diff --git a/Sources/Example/Middlewares/RouteHandlerMiddleware.swift b/Sources/Example/Middlewares/RouteHandlerMiddleware.swift index 9b1f39d..08c9b9a 100644 --- a/Sources/Example/Middlewares/RouteHandlerMiddleware.swift +++ b/Sources/Example/Middlewares/RouteHandlerMiddleware.swift @@ -2,7 +2,7 @@ import HTTPServer import HTTPTypes import Middleware -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) struct RouteHandlerMiddleware< RequestConcludingAsyncReader: ConcludingAsyncReader & Copyable, ResponseConcludingAsyncWriter: ConcludingAsyncWriter & ~Copyable, diff --git a/Sources/Example/Middlewares/TimeoutMiddleware.swift b/Sources/Example/Middlewares/TimeoutMiddleware.swift index 2dab27c..a7b1d2b 100644 --- a/Sources/Example/Middlewares/TimeoutMiddleware.swift +++ b/Sources/Example/Middlewares/TimeoutMiddleware.swift @@ -1,6 +1,6 @@ import Middleware -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) struct TimeoutMiddleware: Middleware { func intercept(input: Input, next: (Input) async throws -> Void) async throws { try await withoutActuallyEscaping(next) { next in @@ -22,7 +22,7 @@ package struct TimeOutError: Error { var underlying: any Error } -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public func withTimeout( in timeout: Clock.Duration, clock: Clock, diff --git a/Sources/Example/Middlewares/TracingMiddleware.swift b/Sources/Example/Middlewares/TracingMiddleware.swift index 243828b..46fcc86 100644 --- a/Sources/Example/Middlewares/TracingMiddleware.swift +++ b/Sources/Example/Middlewares/TracingMiddleware.swift @@ -2,7 +2,7 @@ import HTTPTypes import Middleware import Tracing -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) struct TracingMiddleware: Middleware { func intercept( input: Input, diff --git a/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift b/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift index 27807ad..b8b200b 100644 --- a/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift +++ b/Sources/HTTPServer/AsyncPrimitives/AsyncReader.swift @@ -2,7 +2,7 @@ /// /// ``AsyncReader`` defines an interface for types that can asynchronously read elements /// of a specified type from a source. -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public protocol AsyncReader { /// The type of elements that can be read by this reader. associatedtype ReadElement: ~Copyable, ~Escapable @@ -45,7 +45,7 @@ public protocol AsyncReader { ) async throws(ReadFailure) -> Return } -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) extension AsyncReader { /// Collects elements from the reader up to a specified limit and processes them with a body function. /// diff --git a/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift b/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift index 3dfc896..72b7679 100644 --- a/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift +++ b/Sources/HTTPServer/AsyncPrimitives/ConcludingAsyncReader.swift @@ -4,7 +4,7 @@ /// provide a conclusive element after all reads are completed. This is particularly useful /// for streams that have meaningful completion states beyond just terminating, such as /// HTTP responses that include headers after the body is fully read. -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public protocol ConcludingAsyncReader { /// The underlying asynchronous reader type that produces elements. associatedtype Underlying: AsyncReader, ~Copyable, ~Escapable @@ -38,7 +38,7 @@ public protocol ConcludingAsyncReader { ) async throws -> (Return, FinalElement) } -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) extension ConcludingAsyncReader { /// Processes the underlying async reader until completion and returns only the final element. /// diff --git a/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift b/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift index d5934ad..5f56921 100644 --- a/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift +++ b/Sources/HTTPServer/HTTPRequestConcludingAsyncReader.swift @@ -9,7 +9,7 @@ import NIOHTTPTypes /// and concluding with the HTTP trailer fields received at the end of the request. This type /// follows the ``ConcludingAsyncReader`` pattern, which allows for asynchronous consumption of /// a stream with a conclusive final element. -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader { /// A reader for HTTP request body chunks that implements the ``AsyncReader`` protocol. /// diff --git a/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift b/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift index 07d3766..8cf5be8 100644 --- a/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift +++ b/Sources/HTTPServer/HTTPResponseConcludingAsyncWriter.swift @@ -11,7 +11,7 @@ import NIOHTTPTypes /// /// This writer is designed to work with HTTP responses where the body is streamed in chunks /// and potentially followed by trailer fields. -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public struct HTTPResponseConcludingAsyncWriter: ConcludingAsyncWriter, ~Copyable { /// A writer for HTTP response body chunks that implements the ``AsyncWriter`` protocol. /// diff --git a/Sources/HTTPServer/HTTPServer.swift b/Sources/HTTPServer/HTTPServer.swift index e7eca05..81f905e 100644 --- a/Sources/HTTPServer/HTTPServer.swift +++ b/Sources/HTTPServer/HTTPServer.swift @@ -59,7 +59,7 @@ import SwiftASN1 /// } /// } /// ``` -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public final class Server { /// Starts an HTTP server with a closure-based request handler. /// diff --git a/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift b/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift index 02b2acc..efd4ae5 100644 --- a/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift +++ b/Sources/HTTPServer/HTTPServerClosureRequestHandler.swift @@ -23,7 +23,7 @@ public import HTTPTypes /// } /// } /// ``` -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public struct HTTPServerClosureRequestHandler: HTTPServerRequestHandler { /// The underlying closure that handles HTTP requests private let _handler: diff --git a/Sources/HTTPServer/HTTPServerConfiguration.swift b/Sources/HTTPServer/HTTPServerConfiguration.swift index 7c45add..4b98e90 100644 --- a/Sources/HTTPServer/HTTPServerConfiguration.swift +++ b/Sources/HTTPServer/HTTPServerConfiguration.swift @@ -4,7 +4,7 @@ public import X509 /// /// This structure contains all the necessary configuration options for setting up /// and running an HTTP server, including network binding and TLS settings. -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public struct HTTPServerConfiguration: Sendable { /// Specifies where the server should bind and listen for incoming connections. /// diff --git a/Sources/HTTPServer/HTTPServerRequestHandler.swift b/Sources/HTTPServer/HTTPServerRequestHandler.swift index 5159250..e626185 100644 --- a/Sources/HTTPServer/HTTPServerRequestHandler.swift +++ b/Sources/HTTPServer/HTTPServerRequestHandler.swift @@ -53,7 +53,7 @@ public import HTTPTypes /// } /// } /// ``` -@available(macOS 26.0, *) +@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) public protocol HTTPServerRequestHandler: Sendable { /// Handles an incoming HTTP request and generates a response. /// diff --git a/Tests/HTTPServerTests/HTTPServerTests.swift b/Tests/HTTPServerTests/HTTPServerTests.swift index ef1248f..37bf907 100644 --- a/Tests/HTTPServerTests/HTTPServerTests.swift +++ b/Tests/HTTPServerTests/HTTPServerTests.swift @@ -6,7 +6,7 @@ import Testing @Suite struct HTTPServerTests { @Test - @available(macOS 26.0, *) + @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) func testSimpleAPI() async throws { try await HTTPServer.Server .serve( From 325f527bdde1f054629d29f828d7f8a8d27f050d Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Wed, 6 Aug 2025 13:31:23 +0100 Subject: [PATCH 4/4] Revert "Fix Sendability issue" This reverts commit 9932e76de56eca8b10d97af51f8e9377f16b36cf. --- Sources/Example/Example.swift | 2 +- Sources/Middleware/ChainedMiddleware.swift | 2 +- Sources/Middleware/Middleware.swift | 4 ++-- Sources/Middleware/MiddlewareChain.swift | 14 ++++++-------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Sources/Example/Example.swift b/Sources/Example/Example.swift index 92f6805..16b8bb0 100644 --- a/Sources/Example/Example.swift +++ b/Sources/Example/Example.swift @@ -86,7 +86,7 @@ extension Server { ) async throws -> HTTPResponseConcludingAsyncWriter ), Never - > + > & Sendable ) async throws where RequestHandler == HTTPServerClosureRequestHandler { let chain = middlewareBuilder() diff --git a/Sources/Middleware/ChainedMiddleware.swift b/Sources/Middleware/ChainedMiddleware.swift index 4fae280..4f1096f 100644 --- a/Sources/Middleware/ChainedMiddleware.swift +++ b/Sources/Middleware/ChainedMiddleware.swift @@ -34,7 +34,7 @@ struct ChainedMiddleware: Middleware { /// - Throws: Any error that occurs during processing in either middleware. func intercept( input: Input, - next: @Sendable (NextInput) async throws -> Void + next: (NextInput) async throws -> Void ) async throws { try await first.intercept(input: input) { middleInput in try await second.intercept(input: middleInput, next: next) diff --git a/Sources/Middleware/Middleware.swift b/Sources/Middleware/Middleware.swift index bbecf82..585550d 100644 --- a/Sources/Middleware/Middleware.swift +++ b/Sources/Middleware/Middleware.swift @@ -9,7 +9,7 @@ /// /// - Note: Middleware components are designed to be composable. You can use the /// `MiddlewareChainBuilder` to easily construct middleware chains. -public protocol Middleware: Sendable { +public protocol Middleware { /// The input type that this middleware accepts. associatedtype Input @@ -30,6 +30,6 @@ public protocol Middleware: Sendable { /// - Throws: Any error that occurs during processing. func intercept( input: Input, - next: @Sendable (NextInput) async throws -> Void + next: (NextInput) async throws -> Void ) async throws } diff --git a/Sources/Middleware/MiddlewareChain.swift b/Sources/Middleware/MiddlewareChain.swift index d7c711f..b215c3c 100644 --- a/Sources/Middleware/MiddlewareChain.swift +++ b/Sources/Middleware/MiddlewareChain.swift @@ -8,9 +8,9 @@ /// interface that can represent both simple and complex middleware arrangements. public struct MiddlewareChain: Middleware { private let middlewareFunc: - @Sendable ( + ( Input, - @Sendable (NextInput) async throws -> Void + (NextInput) async throws -> Void ) async throws -> Void /// Creates a new middleware chain from an existing middleware component. @@ -20,9 +20,7 @@ public struct MiddlewareChain: Middleware { /// /// - Parameter middleware: The middleware component to wrap in a chain. public init(middleware: some Middleware) { - self.middlewareFunc = { input, nextInput in - try await middleware.intercept(input: input, next: nextInput) - } + self.middlewareFunc = middleware.intercept } /// Creates a middleware chain using a raw middleware function. @@ -32,9 +30,9 @@ public struct MiddlewareChain: Middleware { /// /// - Parameter middlewareFunc: A closure that implements the middleware's behavior. init( - middlewareFunc: @Sendable @escaping ( + middlewareFunc: @escaping ( Input, - @Sendable (NextInput) async throws -> Void + (NextInput) async throws -> Void ) async throws -> Void ) { self.middlewareFunc = middlewareFunc @@ -53,7 +51,7 @@ public struct MiddlewareChain: Middleware { /// - Throws: Any error that occurs during processing. public func intercept( input: Input, - next: @Sendable (NextInput) async throws -> Void + next: (NextInput) async throws -> Void ) async throws { try await middlewareFunc(input, next) }