diff --git a/Package@swift-5.4.swift b/Package@swift-5.4.swift deleted file mode 100644 index 2718138eb..000000000 --- a/Package@swift-5.4.swift +++ /dev/null @@ -1,73 +0,0 @@ -// swift-tools-version:5.4 -//===----------------------------------------------------------------------===// -// -// This source file is part of the AsyncHTTPClient open source project -// -// Copyright (c) 2018-2019 Apple Inc. and the AsyncHTTPClient project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import PackageDescription - -let package = Package( - name: "async-http-client", - products: [ - .library(name: "AsyncHTTPClient", targets: ["AsyncHTTPClient"]), - ], - dependencies: [ - .package(url: "https://github.com/apple/swift-nio.git", from: "2.42.0"), - .package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.22.0"), - .package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.19.0"), - .package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.13.0"), - .package(url: "https://github.com/apple/swift-nio-transport-services.git", from: "1.11.4"), - .package(url: "https://github.com/apple/swift-log.git", from: "1.4.4"), - .package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"), - ], - targets: [ - .target(name: "CAsyncHTTPClient"), - .target( - name: "AsyncHTTPClient", - dependencies: [ - .target(name: "CAsyncHTTPClient"), - .product(name: "NIO", package: "swift-nio"), - .product(name: "NIOCore", package: "swift-nio"), - .product(name: "NIOPosix", package: "swift-nio"), - .product(name: "NIOHTTP1", package: "swift-nio"), - .product(name: "NIOConcurrencyHelpers", package: "swift-nio"), - .product(name: "NIOHTTP2", package: "swift-nio-http2"), - .product(name: "NIOSSL", package: "swift-nio-ssl"), - .product(name: "NIOHTTPCompression", package: "swift-nio-extras"), - .product(name: "NIOSOCKS", package: "swift-nio-extras"), - .product(name: "NIOTransportServices", package: "swift-nio-transport-services"), - .product(name: "Logging", package: "swift-log"), - .product(name: "Atomics", package: "swift-atomics"), - ] - ), - .testTarget( - name: "AsyncHTTPClientTests", - dependencies: [ - .target(name: "AsyncHTTPClient"), - .product(name: "NIOCore", package: "swift-nio"), - .product(name: "NIOConcurrencyHelpers", package: "swift-nio"), - .product(name: "NIOEmbedded", package: "swift-nio"), - .product(name: "NIOFoundationCompat", package: "swift-nio"), - .product(name: "NIOTestUtils", package: "swift-nio"), - .product(name: "NIOSSL", package: "swift-nio-ssl"), - .product(name: "NIOHTTP2", package: "swift-nio-http2"), - .product(name: "NIOSOCKS", package: "swift-nio-extras"), - .product(name: "Logging", package: "swift-log"), - .product(name: "Atomics", package: "swift-atomics"), - ], - resources: [ - .copy("Resources/self_signed_cert.pem"), - .copy("Resources/self_signed_key.pem"), - ] - ), - ] -) diff --git a/Package@swift-5.5.swift b/Package@swift-5.5.swift index 2718138eb..8ae20ed9c 100644 --- a/Package@swift-5.5.swift +++ b/Package@swift-5.5.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.4 +// swift-tools-version:5.5 //===----------------------------------------------------------------------===// // // This source file is part of the AsyncHTTPClient open source project diff --git a/README.md b/README.md index 611f5ce2c..261fcab56 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ httpClient.execute(request: request, deadline: .now() + .milliseconds(1)) ``` ### Streaming -When dealing with larger amount of data, it's critical to stream the response body instead of aggregating in-memory. +When dealing with larger amount of data, it's critical to stream the response body instead of aggregating in-memory. The following example demonstrates how to count the number of bytes in a streaming response body: #### Using Swift Concurrency @@ -172,7 +172,7 @@ do { for try await buffer in response.body { // for this example, we are just interested in the size of the fragment receivedBytes += buffer.readableBytes - + if let expectedBytes = expectedBytes { // if the body size is known, we calculate a progress indicator let progress = Double(receivedBytes) / Double(expectedBytes) @@ -181,9 +181,9 @@ do { } print("did receive \(receivedBytes) bytes") } catch { - print("request failed:", error) + print("request failed:", error) } -// it is important to shutdown the httpClient after all requests are done, even if one failed +// it is important to shutdown the httpClient after all requests are done, even if one failed try await httpClient.shutdown() ``` @@ -211,17 +211,17 @@ class CountingDelegate: HTTPClientResponseDelegate { } func didReceiveHead( - task: HTTPClient.Task, + task: HTTPClient.Task, _ head: HTTPResponseHead ) -> EventLoopFuture { - // this is executed when we receive HTTP response head part of the request - // (it contains response code and headers), called once in case backpressure + // this is executed when we receive HTTP response head part of the request + // (it contains response code and headers), called once in case backpressure // is needed, all reads will be paused until returned future is resolved return task.eventLoop.makeSucceededFuture(()) } func didReceiveBodyPart( - task: HTTPClient.Task, + task: HTTPClient.Task, _ buffer: ByteBuffer ) -> EventLoopFuture { // this is executed when we receive parts of the response body, could be called zero or more times @@ -283,8 +283,8 @@ Connecting to servers bound to socket paths is easy: ```swift let httpClient = HTTPClient(eventLoopGroupProvider: .createNew) httpClient.execute( - .GET, - socketPath: "/tmp/myServer.socket", + .GET, + socketPath: "/tmp/myServer.socket", urlPath: "/path/to/resource" ).whenComplete (...) ``` @@ -293,9 +293,9 @@ Connecting over TLS to a unix domain socket path is possible as well: ```swift let httpClient = HTTPClient(eventLoopGroupProvider: .createNew) httpClient.execute( - .POST, - secureSocketPath: "/tmp/myServer.socket", - urlPath: "/path/to/resource", + .POST, + secureSocketPath: "/tmp/myServer.socket", + urlPath: "/path/to/resource", body: .string("hello") ).whenComplete (...) ``` @@ -303,11 +303,11 @@ httpClient.execute( Direct URLs can easily be constructed to be executed in other scenarios: ```swift let socketPathBasedURL = URL( - httpURLWithSocketPath: "/tmp/myServer.socket", + httpURLWithSocketPath: "/tmp/myServer.socket", uri: "/path/to/resource" ) let secureSocketPathBasedURL = URL( - httpsURLWithSocketPath: "/tmp/myServer.socket", + httpsURLWithSocketPath: "/tmp/myServer.socket", uri: "/path/to/resource" ) ``` @@ -326,3 +326,14 @@ let client = HTTPClient( ## Security Please have a look at [SECURITY.md](SECURITY.md) for AsyncHTTPClient's security process. + +## Supported Versions + +The most recent versions of AsyncHTTPClient support Swift 5.5 and newer. The minimum Swift version supported by AsyncHTTPClient releases are detailed below: + +AsyncHTTPClient | Minimum Swift Version +--------------------|---------------------- +`1.0.0 ..< 1.5.0` | 5.0 +`1.5.0 ..< 1.10.0` | 5.2 +`1.10.0 ..< 1.13.0` | 5.4 +`1.13.0 ...` | 5.5 diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index cebced614..2d7e744af 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -25,40 +25,45 @@ import XCTest #if os(Linux) || os(FreeBSD) @testable import AsyncHTTPClientTests -XCTMain([ - testCase(AsyncAwaitEndToEndTests.allTests), - testCase(HTTP1ClientChannelHandlerTests.allTests), - testCase(HTTP1ConnectionStateMachineTests.allTests), - testCase(HTTP1ConnectionTests.allTests), - testCase(HTTP1ProxyConnectHandlerTests.allTests), - testCase(HTTP2ClientRequestHandlerTests.allTests), - testCase(HTTP2ClientTests.allTests), - testCase(HTTP2ConnectionTests.allTests), - testCase(HTTP2IdleHandlerTests.allTests), - testCase(HTTPClientCookieTests.allTests), - testCase(HTTPClientInternalTests.allTests), - testCase(HTTPClientNIOTSTests.allTests), - testCase(HTTPClientReproTests.allTests), - testCase(HTTPClientRequestTests.allTests), - testCase(HTTPClientSOCKSTests.allTests), - testCase(HTTPClientTests.allTests), - testCase(HTTPClientUncleanSSLConnectionShutdownTests.allTests), - testCase(HTTPConnectionPoolTests.allTests), - testCase(HTTPConnectionPool_FactoryTests.allTests), - testCase(HTTPConnectionPool_HTTP1ConnectionsTests.allTests), - testCase(HTTPConnectionPool_HTTP1StateMachineTests.allTests), - testCase(HTTPConnectionPool_HTTP2ConnectionsTests.allTests), - testCase(HTTPConnectionPool_HTTP2StateMachineTests.allTests), - testCase(HTTPConnectionPool_ManagerTests.allTests), - testCase(HTTPConnectionPool_RequestQueueTests.allTests), - testCase(HTTPRequestStateMachineTests.allTests), - testCase(LRUCacheTests.allTests), - testCase(RequestBagTests.allTests), - testCase(RequestValidationTests.allTests), - testCase(SOCKSEventsHandlerTests.allTests), - testCase(SSLContextCacheTests.allTests), - testCase(TLSEventsHandlerTests.allTests), - testCase(TransactionTests.allTests), - testCase(Transaction_StateMachineTests.allTests), -]) +@main +struct LinuxMain { + static func main() { + XCTMain([ + testCase(AsyncAwaitEndToEndTests.allTests), + testCase(HTTP1ClientChannelHandlerTests.allTests), + testCase(HTTP1ConnectionStateMachineTests.allTests), + testCase(HTTP1ConnectionTests.allTests), + testCase(HTTP1ProxyConnectHandlerTests.allTests), + testCase(HTTP2ClientRequestHandlerTests.allTests), + testCase(HTTP2ClientTests.allTests), + testCase(HTTP2ConnectionTests.allTests), + testCase(HTTP2IdleHandlerTests.allTests), + testCase(HTTPClientCookieTests.allTests), + testCase(HTTPClientInternalTests.allTests), + testCase(HTTPClientNIOTSTests.allTests), + testCase(HTTPClientReproTests.allTests), + testCase(HTTPClientRequestTests.allTests), + testCase(HTTPClientSOCKSTests.allTests), + testCase(HTTPClientTests.allTests), + testCase(HTTPClientUncleanSSLConnectionShutdownTests.allTests), + testCase(HTTPConnectionPoolTests.allTests), + testCase(HTTPConnectionPool_FactoryTests.allTests), + testCase(HTTPConnectionPool_HTTP1ConnectionsTests.allTests), + testCase(HTTPConnectionPool_HTTP1StateMachineTests.allTests), + testCase(HTTPConnectionPool_HTTP2ConnectionsTests.allTests), + testCase(HTTPConnectionPool_HTTP2StateMachineTests.allTests), + testCase(HTTPConnectionPool_ManagerTests.allTests), + testCase(HTTPConnectionPool_RequestQueueTests.allTests), + testCase(HTTPRequestStateMachineTests.allTests), + testCase(LRUCacheTests.allTests), + testCase(RequestBagTests.allTests), + testCase(RequestValidationTests.allTests), + testCase(SOCKSEventsHandlerTests.allTests), + testCase(SSLContextCacheTests.allTests), + testCase(TLSEventsHandlerTests.allTests), + testCase(TransactionTests.allTests), + testCase(Transaction_StateMachineTests.allTests), + ]) + } +} #endif diff --git a/docker/Dockerfile b/docker/Dockerfile index 1cd4f2140..2d1e57def 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ -ARG swift_version=5.4 -ARG ubuntu_version=bionic +ARG swift_version=5.7 +ARG ubuntu_version=jammy ARG base_image=swift:$swift_version-$ubuntu_version FROM $base_image # needed to do again after FROM due to docker limitation diff --git a/docker/docker-compose.1804.54.yaml b/docker/docker-compose.1804.54.yaml deleted file mode 100644 index dd869549c..000000000 --- a/docker/docker-compose.1804.54.yaml +++ /dev/null @@ -1,19 +0,0 @@ -version: "3" - -services: - - runtime-setup: - image: async-http-client:18.04-5.4 - build: - args: - ubuntu_version: "bionic" - swift_version: "5.4" - - test: - image: async-http-client:18.04-5.4 - command: /bin/bash -xcl "swift test --parallel -Xswiftc -warnings-as-errors $${SANITIZER_ARG-}" - environment: [] - #- SANITIZER_ARG=--sanitize=thread - - shell: - image: async-http-client:18.04-5.4 diff --git a/docker/docker-compose.2004.57.yaml b/docker/docker-compose.2004.57.yaml deleted file mode 100644 index bf6dd6e97..000000000 --- a/docker/docker-compose.2004.57.yaml +++ /dev/null @@ -1,17 +0,0 @@ -version: "3" - -services: - - runtime-setup: - image: async-http-client:20.04-5.7 - build: - args: - base_image: "swiftlang/swift:nightly-5.7-focal" - - test: - image: async-http-client:20.04-5.7 - environment: [] - #- SANITIZER_ARG=--sanitize=thread - - shell: - image: async-http-client:20.04-5.7 diff --git a/docker/docker-compose.2204.57.yaml b/docker/docker-compose.2204.57.yaml new file mode 100644 index 000000000..bea713bad --- /dev/null +++ b/docker/docker-compose.2204.57.yaml @@ -0,0 +1,18 @@ +version: "3" + +services: + + runtime-setup: + image: async-http-client:22.04-5.7 + build: + args: + ubuntu_version: "jammy" + swift_version: "5.7" + + test: + image: async-http-client:22.04-5.7 + environment: [] + #- SANITIZER_ARG=--sanitize=thread + + shell: + image: async-http-client:22.04-5.7 diff --git a/scripts/generate_linux_tests.rb b/scripts/generate_linux_tests.rb index ed887f83c..fe5726f6c 100755 --- a/scripts/generate_linux_tests.rb +++ b/scripts/generate_linux_tests.rb @@ -99,7 +99,10 @@ def createLinuxMain(testsDirectory, allTestSubDirectories, files) file.write '@testable import ' + testSubDirectory + "\n" end file.write "\n" - file.write "XCTMain([\n" + file.write "@main\n" + file.write "struct LinuxMain {\n" + file.write " static func main() {\n" + file.write " XCTMain([\n" testCases = [] for classes in files @@ -109,9 +112,11 @@ def createLinuxMain(testsDirectory, allTestSubDirectories, files) end for testCase in testCases.sort { |x, y| x <=> y } - file.write ' testCase(' + testCase + ".allTests),\n" + file.write ' testCase(' + testCase + ".allTests),\n" end - file.write "])\n" + file.write " ])\n" + file.write " }\n" + file.write "}\n" file.write "#endif\n" end end