519 Commits
Author SHA1 Message Date
hamzahrmalik 5dd84c7bb4 Remove CollectEverythingLogHandler implementation in favour of InMemoryLogHandler from swift-log (#874)
Swift log now has an InMemoryLogHandler. Lets depend on that instead of
having our own `CollectEverythingLogHandler`.

I've added an extension on top, to make it easier to create the logger
too

Result: less code
1.30.2
2025-12-04 13:33:27 +00:00
George Barnett c464bf94ea Don't hold a lock over a continuation in test helpers (#872)
Motivation:

The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.

Modifications:

- Rework the test helpers to avoid holding a lock when a continuation is
created.
- Switch to using NIOLockedValue box

Result:

Lower chance of deadlock
1.30.1
2025-12-01 12:36:23 +01:00
Fabian FettandGeorge Barnett 3c45dbde2d Fix Connection Creation Crash (#873)
### Motivation

When creating a connection, we wrongfully assumed that
`failedToCreateNewConnection` will always be called before
`http*ConnectionClosed` in the `HTTPConnectionPoolStateMachine`. However
this is far from correct. In NIO Futures are fulfilled before
`ChannelHandler` callbacks. Ordering in futures should not be assumed in
such a complex project.

### Change

We change the `http*ConnectionClosed` methods to be noops, if the
connection is in the starting state. We instead wait for the
`failedToCreateNewConnection` to create backoff timers and friends.

rdar://164674912

---------

Co-authored-by: George Barnett <gbarnett@apple.com>
2025-12-01 09:31:32 +01:00
George Barnett ce04df0613 Don't hold a lock over a continuation in Transaction (#871)
Motivation:

The various 'withMumbleContinuation' APIs are supposed to be invoked
synchronously with the caller. This assumption allows a lock to be
acquired before the call and released from the body of the
'withMumbleContinuation' after e.g. storing the continuation. However
this isn't the case and the job may be re-enqueued on the executor
meaning that this is pattern is vulnerable to deadlocks.

Modifications:

- Drop and reacquire the lock in Transaction

Result:

Lower chance of deadlock
2025-11-26 14:13:29 +00:00
Cory Benfield b2faff932b Drop Swift 5.10 (#870) 1.30.0 2025-11-07 08:50:46 -05:00
Rick Newton-Rogers b2ae84569c Add explicit read permissions to workflows (#867)
Motivation:

* More secure GitHub Actions workflows

Modifications:

Add explicit 'contents: read' permissions to workflows that did not have
explicit permissions defined. This follows GitHub Actions security best
practices by limiting the default GITHUB_TOKEN permissions.

Result:

An extra layer of security.
2025-10-30 16:43:10 +00:00
Cory Benfield efb14fec9f Resolve SendableMetatype issues (#865)
This resolves warnings around SendableMetatype in the AHC codebase, and
gets our 6.2 builds working again.
1.29.1
2025-10-15 13:06:05 +01:00
Cory Benfield 0ce87cb315 Avoid delays when inserting HTTP/2 handlers. (#864)
Motivation

Right now, we insert HTTP/2 handlers in a callback on a future that is
done very late. The result of this is that an entire ALPN negotiaton
_can_ complete before this callback is attached. That can in rare cases
cause the HTTP/2 handler to miss the server preamble, because it gets
added too late.

Modifications

This patch refactors the existing code to close that window. It does so
by passing a promise into the connection path and completing that
promise _on_ the event loop where we add the ALPN handlers, which should
ensure this will execute immediately when the ALPN negotiation
completes. Immportantly, we attach our promise callbacks to that promise
_before_ we hand it off, making sure the timing windows go away.

Results

Timing window is closed
2025-10-14 15:43:56 +01:00
Konrad `ktoso` Malawski 353bbc8cc2 [Tracing] Implement trace header context propagation (#862) 2025-10-10 08:35:50 +01:00
Konrad `ktoso` Malawski c2a3a2cfb7 [Tracing] Default tracer to global bootstrapped tracer (#861) 2025-10-09 17:01:05 +09:00
8430dd49d4 Introduce built-in swift-distributed-tracing support (#857)
Co-authored-by: Moritz Lang <16192401+slashmo@users.noreply.github.com>
Co-authored-by: George Barnett <gbarnett@apple.com>
1.29.0
2025-10-07 16:30:31 +09:00
Rick Newton-Rogers 31c8b047b5 Enable Swift 6.2 jobs in CI (#859)
Motivation:

Swift 6.2 has been released, we should add it to our CI coverage.

Modifications:

Add additional Swift 6.2 jobs where appropriate in main.yml,
pull_request.yml

Result:

Improved test coverage.
2025-09-22 14:28:49 +01:00
Cory Benfield 7dc119c7ed Add support for HTTP/1 connection pre-warming (#856)
Motivation

This patch adds support for HTTP/1 connection pre-warming. This allows
the user to request that the HTTP/1 connection pool create and maintain
extra connections, above-and-beyond those strictly needed to run the
pool. This pool can be used to absorb small spikes in request traffic
without increasing latency to account for connection creation.

Modifications

- Added new configuration properties for pre-warmed connections.
- Amended the HTTP/1 state machine to create new connections where
necessary.
- Added state machine tests.

Results

Pre-warmed connections are available.
1.28.0
2025-09-09 09:55:45 +01:00
Gwynne Raskind 254d340961 Fix trailing space in ConnectionPool.Key string (#855)
Motivation:

The trailing space is visible in log message metadata, and depending
upon the log handler in use, will sometimes be visible due to quoting.

Modifications:

Just remove the trailing space.

Result:

There won't be a trailing space in the key anymore. This has no
functional impact whatsoever as far as I was able to determine.
1.27.0
2025-08-24 16:55:12 -04:00
Johannes Weiss abb11d5b90 make HTTPClient Sendable without @unchecked (#852)
Previously, `HTTPClient` used `@unchecked Sendable`, now it's compiler
checked.
2025-08-12 10:04:16 +01:00
George Barnett 2edac1df19 Deflake HTTP2ConnectionTests/testSimpleGetRequest (#851)
Motivation:

testSimpleGetRequest asserts right after submitting the request for
execution that no streams have been closed. While unlikely there's
nothing to prevent this assertion from failing (and indeed it has
failed): the request may have executed immediately and the stream closed
before checking the delegate.

Modifications:

- Remove the assertion

Result:

Tests are less flaky
2025-08-04 10:17:30 +01:00
Raphael 64021b3066 Enable release mode builds (#850)
### Motivation:

Some errors do not show up in debug builds. Enabling release mode builds
improves the CI coverage.

### Modifications:

Enable release mode builds for pull requests and scheduled builds on
main.

### Result:

Improved CI coverage.
2025-07-30 08:55:42 +01:00
jessezamora 0b6f957d33 Use Int64.random instead of .randomElement in HTTPConnectionPool.calculateBackoff (#848)
Fixes #847. 

Motivation:

On 32-bit systems, using .randomElement on a range larger than what can
fit in Int32 (Int) causes a crash. After only 26 or 27 retries of a
request using HTTPClient, the calculateBackoff method would run into
this and crash consistently on an armv7 (32-bit) device.

Modifications:

A one-line fix to opt to using Int64.random on the same jitterRange
instead of .randomElement, which works as expected without crashing on
32-bit systems.

Result:

The HTTPClient now works as expected and can perform as many retries as
needed without crashing.

I tested this on my armv7 board doing the retries, and ran up to several
hundred repetitions after a few hours with no crashes as was happening
before.

@Lukasa
2025-07-11 14:33:27 +00:00
George Barnett 20216dfe9d Drop support for Swift 5.9 (#845) 2025-05-22 11:56:34 +01:00
George Barnett 6023598316 Fix 5.9 build (#844)
Motivation:

An oversight in 373862a meant that 5.9 wasn't actually dropped which
means that the use of 'nonisolated(unsafe)' in 0e715a27 broke users of
5.9.

Modifications:

- Add back a 5.9 path

Result:

- Builds on 5.9
- Resolves #843
1.26.1
2025-05-22 11:07:10 +01:00
George Barnett 3b265e6a00 Enable warnings as errors in CI (#842)
Motivation:

Now that strict concurrency has been adopted the AHC should avoid
regressing by treating all warnings as errors in CI.

Modifications:

- Treat warnings as errors in CI

Result:

Stricter CI
1.26.0
2025-05-08 10:51:33 +01:00
George Barnett 0397ea8392 Fix sendability issues in tests (#841)
Motivation:

The tests shouldn't be making sendability violations.

Modifications:

Fix the warnings

Result:

- No warnings
- Strict concurrency is adopted!
2025-05-01 09:38:10 +00:00
George Barnett 6b5f8c9679 Fix a few more Sendability warnings in Sources (#840)
Motivation:

There are a couple of sendability warnings leftover in Sources.

Transaction moves a closure into a task. The closure isn't Sendable (and
shouldn't be). However, higher up the stack there's a closure which
generates the non-sendable closure which can be sendable.

Modifications:

- Pass the sendable closure generating closure down rather
- Add a few more explicit sendable annotations

Result:

Fewer warnings
2025-04-30 16:40:50 +01:00
Cory Benfield beb2637432 Clean up Task error handling. (#839)
Motivation

We have some Task error handling functions that are generic for no
apparent reason. They're also typically called from contexts where they
also report the error to the delegate, but one of the call sites doesn't
do that. So add a test for that as well.

Modifications

- Rewrite Task.fail(with:delegate:) to be non-generic.
- Add a call to the delegate error handler on the path that is missing
it.
- Add a test for that call

Results

Cleaner, easier to follow code
2025-04-30 13:57:00 +00:00
George Barnett 7e6f9cf833 Make the ResponseAccumulator Sendable (#838)
Motivation:

The response accumulator is a delegate which must be sendable as it's
passed across isolation domains.

Modifications:

- Make delegates have a sendable requirement
- Make the response accumulator sendable

Result:

Delegates, and the response accumulator, are sendable
2025-04-30 14:37:07 +01:00
George Barnett c61298e4d3 Make RequestBag conform to Sendable (#837)
Motivation:

RequestBag conforms to HTTPExecutableRequest to must be Sendable.

Modifications:

- Move event-loop bound state to a loop-bound box
- Remove redundant event-loop checks (they are performed by the loop
bound box)

Result:

Fewer warnings
2025-04-30 10:50:39 +01:00
George Barnett 716fb3f983 Make the file download delegate sendable (#834)
Motivation:

Delegates can be passed from any thread and are executed on an arbitrary
event loop. That means they need to be Sendable. Rather than making them
all Sendable in one go, we'll do the larger ones separately.

Modifications:

- Make FileDownloadDelegate sendable

Result:

Safe to pass FileDownloadDelegate across isolation domains
2025-04-30 10:28:05 +01:00
George Barnett 4de7a26ca5 Fix a number of sendable warnings in test utilities (#836)
Motivation:

The test utilities have a number of sendability issues.

Modifications:

- Fix the issues

Result:

Fewer warnings
2025-04-29 18:48:45 +01:00
George Barnett a4fcd701e9 Make body stream writer sendable (#835)
Motivation:

The body stream writer can be sent across isolation domains so should be
sendable.

Modifications:

- Make it explicitly sendable
- Add appropriate preconcurrency annotations
- Wrap an iterator from swift-algorithms as it hasn't yet annotated its
types with Sendable

Result:

Body stream writer is sendable
2025-04-29 15:38:05 +01:00
George Barnett 086524fd8a Fix sendability issues in the connection pool (#833)
Motivation:

The connection pool holds much of the low level logic in AHC. We should
fix its sendability issues before moving to higher levels.

Modifications:

- Make HTTP1ConnectionDelegate and HTTP2Delegate sendable, this requires
passing IDs rather than connections to their methods
- Make HTTPConnectionRequester sendable and have its methods take
Sendable views of the HTTP1Connection and HTTP2Connection types
- Add sendable views to HTTP1Connection and HTTP2Connection
- Mark HTTP1Connection and HTTP2Connection as not sendable
- Make HTTPRequestExecutor and HTTPExecutableRequest sendable
- Update tests

Result:

Connection pool has stricter sendability requirements
2025-04-28 15:33:38 +01:00
George Barnett 0e715a2793 Fix a few simple sendability issues (#832)
Motivation:

We're about to go on a sendability journey. Let's pick some low hanging
fruit to get started.

Modifications:

- Add a few assume-isolated calls
- Stop using static var
- Use a dispatch group instead of a work item to wait for work to be
done.

Result:

Fewer warnings
2025-04-28 14:17:36 +01:00
George Barnett efb08f9641 Add explicit sendability annotations (#831)
Motivation:

As part of adopting strict concurrency all public types should be
explicit about whether they are sendable or not.

Modifications:

- Add explicit sendability annotations to a number of types

Result:

Sendability is explicit
2025-04-28 10:42:07 +01:00
a3d00a65b9 Add "debug initializer" hook for channels (#801)
Motivation:

As requested in #596, it can be handy to have a lower-level access to
channels (HTTP/1 connection, HTTP/2 connection, or HTTP/2 stream) to
enable a more fine-grained interaction for, say, observability, testing,
etc.

Modifications:

- Add 3 new properties (`http1_1ConnectionDebugInitializer`,
`http2ConnectionDebugInitializer` and
`http2StreamChannelDebugInitializer`) to `HTTPClient.Configuration` with
access to the respective channels. These properties are of `Optional`
type `@Sendable (Channel) -> EventLoopFuture<Void>` and are called when
creating a connection/stream.

Result:

Provides APIs for a lower-level access to channels.

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
Co-authored-by: David Nadoba <d_nadoba@apple.com>
Co-authored-by: George Barnett <gbarnett@apple.com>
2025-04-25 12:11:02 +00:00
George Barnett 373862aa09 Drop support for Swift 5.9 (#830)
Motivation:

Now that Swift 6.1 has been released, Swift 5.9 has dropped out of the
support window.

Modifications:

- Bumpt tools versions to 5.9
- Disable 5.9 workflows

Result:

5.9 is no longer supported
2025-04-25 11:12:46 +00:00
Rick Newton-Rogers 16886fd35d Enable Swift 6.1 jobs in CI (#827)
Motivation:

Swift 6.1 has been released, we should add it to our CI coverage.

Modifications:

Add additional Swift 6.1 jobs where appropriate in main.yml,
pull_request.yml
Result:

Improved test coverage.
2025-04-14 10:51:09 +01:00
Gus Cairo 2064247c2b Update expired test cert (#824)
The certificate for `AsyncAwaitEndToEndTests.testDnsOverride` has
expired: this PR updates it.
2025-04-01 15:42:41 +01:00
Rick Newton-Rogers 01908f4f53 Add static SDK CI workflow (#823)
Add static SDK CI workflow which runs on commits to PRs, merges to main
and daily on main.
2025-03-14 10:43:01 +00:00
Cory Benfield a413b779fb Work around Foundation revert even more (#822)
Since #813, Foundation have backported their revert to 6.1. Now only 6.0
is the weird one.
2025-03-11 11:51:33 +00:00
Rick Newton-Rogers f9fb26f401 Only apply standard swift settings on valid targets (#821)
Only apply standard swift settings on valid targets. The current check
ignores plugins but that is not comprehensive enough.
2025-03-07 15:04:15 +00:00
Greg Cotten 31122eaf7c Add Request/Response History to all public Response types (#817)
Work to close
https://github.com/swift-server/async-http-client/issues/790

The fact that `HTTPClient.Request` is not Sendable make me think we're
going to need to store something else, such as a `URL` and
`HTTPRequestHead`, instead?
2025-03-03 15:48:27 +00:00
Rick Newton-Rogers 2dbcdf2d4f Rename nightly_6_1 params to nightly_next (#820)
Rename nightly_6_1 params to nightly_next; see
https://github.com/apple/swift-nio/pull/3122
2025-03-03 14:51:02 +00:00
Greg Cotten da621ce4a8 Add didVisitURL delegate method (#816)
Trying to pave the way for closing
https://github.com/swift-server/async-http-client/issues/790 with some
direction from @Lukasa.

I have no idea where is best to insert this new delegate method. I'm
currently doing it first thing in `receiveResponseHead0`, and not using
an EventLoopFuture for back pressure management. The state machine seems
pretty fragile and I don't want to leave too much of an imprint. Trying
to be a part of an EventLoopFuture chain seems really complicated and
would really leave a mark on the codebase, so I'm wondering if it's
possible to just warn the user "do not block"?

Anyway, just a jumping-off point and happy to take direction!
2025-02-21 08:30:24 +00:00
Greg Cotten ad262cc3d2 Propagate HTTPClient.Task<Response> failures to subsequent redirect tasks (#814)
Discussed in
https://github.com/swift-server/async-http-client/issues/753
2025-02-20 10:22:40 +00:00
Greg Cotten d05bf23650 Add head property to FileDownloadDelegate's Progress/Response struct (#811)
I needed a way to use a `FileDownloadDelegate` task to fish out the
recommended file name.
```swift
let response = try await downloadTask.get()

// access content-disposition
response.head.headers.first(name: "Content-Disposition")
```

The `head` property is an explicitly unwrapped optional because there is
no "default value" to set it to, and it won't be accessed by the user
until it's already been set anyway. This is a little inelegant, so I
could change it to something like below where I fill in bogus init data,
but that seems worse for some reason.
```swift
public struct Progress: Sendable {
    public var totalBytes: Int?
    public var receivedBytes: Int
    public var head: HTTPResponseHead
}

private var progress = Progress(
    totalBytes: nil,
    receivedBytes: 0,
    head: .init(
        version: .init(major: 0, minor: 0),
        status: .badRequest
    )
)
```
2025-02-18 15:18:55 +00:00
Cory Benfield 333f51104b Work around Foundation revert (#813)
Motivation

Foundation has reverted several of the changes of behaviour in the URL
type, leaving 6.0 and 6.1 with a different behaviour on non-Apple
platforms than all other versions.

We should tolerate that.

Modifications

Update the tests to understand the difference.

Result

Tests pass
1.25.2
2025-02-17 17:17:16 +00:00
Cory Benfield 3b4942f5b3 Remove misuse of EmbeddedEventLoop (#812)
Motivation

EmbeddedEventLoop is not thread-safe, which means that outside of very
rare use-cases it's not safe to use it in Swift Concurrency.

Modifications

Replace invalid uses of EmbeddedEventLoop with NIOAsyncTestingEventLoop

Result

Better safety
2025-02-17 15:43:34 +00:00
Johannes WeissandJohannes Weiss b645ad4082 fix 5.10 compile on Ubuntu 24.04 (Noble) for Intel (x86_64) (#810)
Specifically Swift 5.10 _on Intel on Ubuntu Noble (24.04)_ has a crazy
bug which leads to compilation failures in a `#if compiler(>=6.0)`
block: https://github.com/swiftlang/swift/issues/79285 .

This workaround fixes the compilation by _changing the whitespace_.

Thanks @gwynne for finding this workaround!

---------

Co-authored-by: Johannes Weiss <johannes@jweiss.io>
1.25.1
2025-02-11 12:25:31 +00:00
Johannes WeissandJohannes Weiss 89dc8d0068 baby steps towards a Structured Concurrency API (#806)
At the moment, `HTTPClient`'s entire API surface violates Structured
Concurrency. Both the creation & shutdown of a HTTP client as well as
making requests (#807) doesn't follow Structured Concurrency. Some of
the problems are:

1. Upon return of methods, resources are still in active use in other
threads/tasks
2. Cancellation doesn't always work

This PR is baby steps towards a Structured Concurrency API, starting
with start/shutdown of the HTTP client.

Co-authored-by: Johannes Weiss <johannes@jweiss.io>
1.25.0
2025-02-06 17:11:37 +00:00
Rick Newton-Rogers 81384de61c CI use 6.1 nightlies (#805)
CI use 6.1 nightlies now that Swift development is happening in the 6.1
branch
2025-01-30 09:43:36 +00:00
Allan Shortlidge 60fa3dcfc5 Add missing import of Network module (#804) 1.24.2 2025-01-29 18:42:58 +00:00