103 Commits

Author SHA1 Message Date
Mads Odgaard c5784ca815 Replace import Foundation with FoundationEssentials (#897)
Replaces all the foundation imports.

One issue is that `HTTPClient.init?(httpsURLWithSocketPath socketPath:
String, uri: String = "/")` uses `addingPercentEncoding()` from
Foundation. So instead, we use a pure Swift impl. that does the same.

We also need to disable default traits from `swift-configuration` to
prevent linking Foundation, because the `JSON` trait does that.

This also adds a linkage test to prevent regressions to CI.
2026-03-13 13:23:14 +00:00
hamzahrmalik ba1d03d8d1 Add option to retain request method on 301/302/303 redirects (#887)
Add a configuration option to retain the HTTP method and body receiving
301 or 302 responses.

Currently we automatically change the method to GET, and remove the
body, before following a 301 or 302. This is compliant with the fetch
specification: https://fetch.spec.whatwg.org/#http-redirect-fetch

However, it is useful to be able to override this behaviour and retain
the method and body.

Changes
- Add a new struct to encapsulate the (now 4) arguments of the follow
case of the redirect mode
- Add new options `retainHTTPMethodAndBodyOn301` and
`retainHTTPMethodAndBodyOn302`. Defaults to false because thats the
existing behaviour today
- When it is true, do not convert requests to GET after following a
redirect
- Note: this does not affect 307/308 (or any other) redirects. They
always preserve their method

---------

Co-authored-by: Fabian Fett <fabianfett@apple.com>
2026-02-20 14:10:24 +00:00
Cory Benfield 52ed9d1720 Use a smaller max buffer size on 32-bit platforms (#886)
Resolves #884
2026-02-11 10:11:12 +00:00
Cory Benfield b2faff932b Drop Swift 5.10 (#870) 2025-11-07 08:50:46 -05:00
Konrad `ktoso` Malawski 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>
2025-10-07 16:30:31 +09: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 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
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
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
Johannes 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>
2025-02-06 17:11:37 +00:00
Johannes Weiss 2119f0d9cc fix 784: dont crash on huge in-memory bodies (#785)
fixes #784 

`writeChunks` had 3 bugs:
1. An actually wrong `UnsafeMutableTransferBox` -> removed that type
which should never be created
2. A loooong future chain (instead of one final promise) -> implemented
3. Potentially infinite recursion which lead to the crash in #784) ->
fixed too
2024-11-26 14:52:39 +00:00
Rick Newton-Rogers c621142327 Adopt GitHub actions (#780)
Migrate CI to use GitHub Actions.

### Motivation:

To migrate to GitHub actions and centralised infrastructure.

### Modifications:

Changes of note:
* Adopt swift-format using rules from SwiftNIO.
* Remove scripts and docker files which are no longer needed.
* Disabled warnings-as-errors on Swift 6.0 CI pipelines for now.

### Result:

Feature parity with old CI.
2024-10-29 15:01:46 +00:00
Agam Dua acaca2d50d Added: ability to set basic authentication on requests (#778)
Motivation:

As an HTTP library, async-http-client should have authentication
support.

Modifications:

This adds a `setBasicAuth()` method to both HTTPClientRequest and
`HTTPClient.Request` and their related unit tests.

Result:

Library users will be able to leverage this method to use basic
authentication on their requests without implementing this in their own
projects.

Note: I also ran the tests (`swift test`) with the
`docker.io/library/swift:6.0-focal` and
`docker.io/library/swift:5.10.1-focal` to ensure linux compatibility.

Signed-off-by: Agam Dua <agam_dua@apple.com>
2024-10-21 16:27:28 +01:00
Johannes Weiss 0bd9111ca7 mark HTTPClient.Response Sendable (#759)
`HTTPClient.Response` is trivially `Sendable`, let's mark it `Sendable`.
2024-08-07 08:28:39 -07:00
aryan-25 54d1006dc9 Add leading slash in relative URL requests if necessary (#747) 2024-07-09 12:47:07 +02:00
aryan-25 07536f6a4e Resolve ambiguity issue for the stream function, remove @deprecated marking from the original implementation, and make argument labels consistent. (#749) 2024-07-03 16:14:47 +01:00
aryan-25 4316ecae09 Add support for request body to be larger than 2GB on 32-bit devices (#746)
### Motivation:

- The properties that store the request body length and the cumulative number of bytes sent as part of a request are of type `Int`. 
- On 32-bit devices, when sending requests larger than `Int32.max`, these properties overflow and cause a crash.
- To solve this problem, the properties should use the explicit `Int64` type.

### Modifications:

- Changed the type of the `known` field of the `RequestBodyLength` enum to `Int64`.
- Changed the type of `expectedBodyLength` and `sentBodyBytes` in `HTTPRequestStateMachine` to `Int64?` and `Int64` respectively.
- Deprecated the `public var length: Int?` property of `HTTPClient.Body` and backed it with a new property: `contentLength: Int64?`
  - Added a new initializer and "overloaded" the `stream` function in `HTTPClient.Body` to work with the new `contentLength` property.
  - **Note:** The newly added `stream` function has different parameter names (`length` -> `contentLength` and `stream` -> `bodyStream`) to avoid ambiguity problems.
- Added a test case that streams a 3GB request -- verified this fails with the types of the properties set explicitly to `Int32`. 

### Result:

- 32-bit devices can send requests larger than 2GB without integer overflow issues.
2024-06-28 11:33:04 +02:00
Rick Newton-Rogers de7c84a607 Bump minimum Swift version to 5.7 (#712)
Motivation:

Now that Swift 5.9 is GM we should update the supported versions and
remove 5.6

Modifications:

* Update `Package.swift`
* Remove `#if swift(>=5.7)` guards
* Delete the 5.6 docker compose file and make a 5.10 one
* Update docs

Result:

Remove support for Swift 5.6, add 5.10
2023-10-04 17:43:21 +01:00
David Nadoba 75d7f63abf Automatically chunk large request bodies (#710)
* ChunkedCollection

* Use swift-algorithms

* SwiftFormat

* test chunking

* add documentation

* SwiftFormat

* fix old swift versions

* fix older swift versions

second attempt

* fix old swift versions

third attempt

* fix old swift versions

fourth attempt

* update documentation
2023-09-06 11:08:09 +01:00
David Nadoba d62c475401 Drop Swift 5.5 (#686) 2023-04-14 17:05:09 +01:00
David Nadoba b9029ef67c Add support for custom cancellation error (#683) 2023-04-13 17:00:03 +01:00
Cory Benfield 343cdf4639 Fix documentation and add support for CI-ing it (#679)
* Fix documentation and add support for CI-ing it

* Fixup license header
2023-04-11 13:35:46 +01:00
Cory Benfield 864c8d9e0e Mark Task.wait() noasync and provide Task.get() (#668)
Motivation

Task.wait() is a convenience method to avoid needing to wait for the
response future. This has had the effect of "laundering" a noasync
warning from EventLoopFuture.wait(), hiding it within a purely sync call
that may itself be used in an async context.

We should discourage using these and prefer using .get() instead.

Modifications

Mark Task.wait() noasync.
Add Task.get() for backward compatibility.

Result

Safer migration to Swift concurrency
2023-02-14 01:48:22 -08:00
Fabian Fett f65f45b727 Fix Request streaming memory leak (#665) 2023-02-07 17:18:56 +01:00
Felix Schlegel 817d9aa99f Make Task.logger accessible to delegate implementations outside of Package (#587)
Motivation:

This change was proposed in issue
[#389](https://github.com/swift-server/async-http-client/issues/389).
Users writing their own `HttpClientResponseDelegate` implementation
might want to emit log messages to the `task`'s `logger`.

Modifications:

Changed the access level of `Task`'s `logger` property from `internal`
to `public`.

Result:

Users can access the `logger` property of a `Task` outside of the
`async-http-client`.
2023-01-22 09:32:01 -08:00
David Nadoba 0bdc425a84 Remove #if compiler(>=5.5) (#641)
* Remove `#if compiler(>=5.5)`

* Run SwiftFormat
2022-10-12 16:18:47 +01:00
David Nadoba 0b5bec741b Replace NIOSendable with Sendable (#640) 2022-10-12 08:50:28 +01:00
David Nadoba 9937d8751a Handle ResponseAccumulator not being able to buffer large response in memory (#637)
* Handle ResponseAccumulator not being able to buffer large response in memory

Check content length header for early exit

* Add test which currently hangs indefinitely

* Run `generate_linux_tests.rb` and `SwiftFormat`

* Print type and value if assert fails

* Run `generate_linux_tests.rb` and `SwiftFormat`

* Remove duplicate test due too merge conflict

* Validate that maxBodySize is positive

* Address review comments
2022-10-10 11:18:58 +01:00
Fabian Fett 897d49aa1b Replace Lock with NIOLock (#628)
SwiftNIO 2.42.0 has deprecated Lock and replaced it with a new NIOLock. This commit removes all uses of Lock and replaces them with NIOLock. Further, now, we must require SwiftNIO 2.42.0
2022-09-27 15:42:47 +02:00
David Nadoba c3c90aab58 Adopt Sendable (#621) 2022-08-25 11:45:13 +02:00
David Nadoba fc510a39cf Fix thread leak in FileDownloadDelegate (#614)
* Fix thread leak in `FileDownloadDelegate`

* `SwiftFormat`

* Add a shared file IO thread pool per HTTPClient

* User bigger thread pool and initlize lazily during first file write

* thread pool is actually not used in tests

* Update documentation

* fix review comments

* make `fileIOThreadPool` internal

* Add test to verify that we actually share the same thread pool across all delegates for a given HTTPClient

Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-08-18 11:55:55 +02:00
Cory Benfield 5e3e58dafd Use Docc for documentation (#613)
Motivation

Documentation is nice, and we can help support users by providing useful
clear docs.

Modifications

Add Docc to 5.6 and later builds
Make sure symbol references work
Add overview docs

Result

Nice rendering docs
2022-08-09 16:23:14 +01:00
Karl 609b4368b8 Used vendored base64 encoding implementation rather than Foundation.Data (#539) 2022-01-21 15:28:26 +01:00
David Nadoba c2805dfa4e Prepare async/await API for public release (#531) 2022-01-14 14:35:17 +01:00
Karl 6474d8d2b2 Add HTTPClient.Body.bytes as an alternative to .data (#534) 2022-01-13 14:19:48 +00:00
David Nadoba c4feafd813 Refactor redirect logic to be reusable for async/await (#522)
* refactor RedirectHandler
- `redirectState` is no longer a property of `HTTPClient.Request`. RedirectHandler now stores this state directly and therefore no longer optional.
- we no longer count the number of allowed redirects down. Instead the number of redirects is dervied from `self.visited.count` and we compare it to the maxRedirect to check if we git the limit.

* `HTTPClient.Configuration.RedirectConfiguration.Configuration` is now called `HTTPClient.Configuration.RedirectConfiguration.Mode`
only two `Configuration`s left in the type name

* add redirect logger test
2021-12-08 19:16:06 +01:00
David Nadoba 5ce7377a8a Add HTTPClientReuqest.Prepared (#511)
* add HTTPClientReuqest.Prepared

* make `prepared()` an init of `Prepared`

* make all stored properties of `Prepared` `var`s
2021-12-03 09:54:01 +01:00
David Nadoba 99bd384b38 Refactor deconstructURL and scheme parsing (#504)
* make `Scheme` a type

* introduce new Endpoint type

* use endpoint as storage in `HTTPClient.Request`

* fix merge conflicts

* rename Endpoint to DeconstructedURL

* swift-format

* make `DeconstructedURL` properties `var`'s

* move scheme into global namespace

- rename `useTLS` to `usesTLS` where posible without breaking public API
- only import Foundation.URL

* fix review comments
2021-12-01 13:03:09 +01:00
Karl f1a91872c5 Introduce a ConnectionTarget enum (#501)
* Add a ConnectionPool.Host enum

* Move Host out as a top-level ConnectionTarget type, and use it in Request.
2021-11-30 18:29:38 +01:00
Karl f2c2f73fb9 Refactor URL component extraction (#485)
* Refactor URL component extraction

* Remove superfluous test message

Co-authored-by: Fabian Fett <fabianfett@apple.com>
Co-authored-by: David Nadoba <d_nadoba@apple.com>
2021-11-26 12:49:43 +01:00
David Nadoba 0ed00b8b36 Always overwrite Transport-Encoding and Content-Length headers (#479) 2021-11-23 10:22:57 +01:00
Fabian Fett 2bd88855b4 Remove deprecated connection pool (#443)
- Remove now unused Connection/ConnectionPool
- Removed TaskHandler
- Remove ResponseReadBuffer
- Removed further now unused code
- Remove unused imports
- Remove test util `RecordingHandler`
2021-09-29 18:42:24 +02:00
Fabian Fett 2565dfe0dc [HTTPConnectionPool] Implementation switch (#427) 2021-09-24 09:28:09 +02:00
Fabian Fett eab2a84b1c Use explicit NIO imports (#407)
* Use explicit NIO imports for `NIOCore`, `NIOPosix` and `NIOEmbedded`
* Updated dependencies
2021-08-19 21:11:49 +02:00
Fabian Fett bccb075309 Refactor Request Validation (#391)
- Refactored code from `TaskHandler` into new method `HTTPClient.Request.createRequestHead` that creates an `HTTPRequestHead` and matching `RequestFramingMetadata`
- Added required property `requestFramingMetadata` to `HTTPExecutingRequest`
- Added property `requestFramingMetadata` to `RequestBag`

Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-07-07 19:50:00 +02:00
Fabian Fett a9aee2675f Add HTTPScheduledRequest and HTTPExecutingRequest (#384)
- Adding four new protocols:
  - `HTTPExecutingRequest` a protocol representing an HTTP task that is executed on a ChannelHandler.
  - `HTTPScheduledRequest` a protocol representing an HTTP task that is scheduled for execution, but in a waiting state (example: Waiting for an idle connection in the connection pool).
  - `HTTPRequestExecutor` a protocol that can be used from the `HTTPExecutingRequest` abstracting away functionality that will normally be implemented by a `ChannelHandler`
  - `HTTPRequestScheduler` a protocol that can be used from the `HTTPScheduledRequest` abstracting away functionality that will normally be implemented by a `ConnectionPool`
- An implementation of the `HTTPExecutingTask` and `HTTPScheduledRequest` called `RequestBag`. It implements  our current API using the new protocols

Co-authored-by: George Barnett <gbarnett@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
2021-07-07 13:44:48 +02:00
David Evans 3fd0658dd9 Implement SOCKS proxy functionality (#375)
Add a new Proxy type to enable a HTTPClient to send requests via a SOCKSv5 Proxy server.
2021-06-18 13:02:58 +01:00
Mads Odgaard ca722d8337 Support request specific TLS configuration (#358)
Adds support for request-specific TLS configuration:
Request(url: "https://webserver.com", tlsConfiguration: .forClient())
2021-05-07 13:47:02 +01:00