Commit Graph
290 Commits
Author SHA1 Message Date
Rick Newton-RogersandGitHub 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 DuaandGitHub 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
Rick Newton-RogersandGitHub 0a9b72369b workaround Foundation.URL behavior changes (#777)
`Foundation.URL` has various behavior changes in Swift 6 to better match
RFC 3986 which impact AHC.

In particular it now no longer strips the square brackets in IPv6 hosts
which are not tolerated by `inet_pton` so these must be manually
stripped.

https://github.com/swiftlang/swift-foundation/issues/957
https://github.com/swiftlang/swift-foundation/issues/958
https://github.com/swiftlang/swift-foundation/issues/962
2024-10-03 03:02:00 -07:00
15dbe6dcee Add an option to enable Multipath TCP on clients (#766)
Multipath TCP (MPTCP) is a TCP extension allowing to enhance the
reliability of the network by using multiple interfaces. This extension
provides a seamless handover between interfaces in case of deterioration
of the connection on the original one. In the context of iOS and Mac OS
X, it could be really interesting to leverage the capabilities of MPTCP
as they could benefit from their multiple interfaces (ethernet + Wi-fi
for Mac OS X, Wi-fi + cellular for iOS).

This contribution introduces patches to HTTPClient.Configuration and
establishment of the Bootstraps. A supplementary field "enableMultipath"
was added to the configuration, allowing to request the use of MPTCP.
This flag is then used when creating the channels to configure the
client.

Note that in the future, it might also be potentially interesting to
offer more precise configuration options for MPTCP on MacOS, as the
Network framework allows also to select a type of service, instead of
just offering the option to create MPTCP connections. Currently, when
enabling MPTCP, only the Handover mode is used.

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2024-09-20 12:22:17 +01:00
Ian AndersonandGitHub 6df8e1c17e Explicitly import locale modules (#771)
The Darwin module is slowly being split up, and as it gets further
along, it will stop importing some of the split-out modules like the one
for locale.h that provides newlocale() and other locale API. However,
there's a wrinkle that on platforms with xlocale, it's xlocale.h that
provides most of the POSIX locale.h functions and not locale.h, so
prefer the xlocale module when available.
2024-09-14 07:55:55 +01:00
Fabian FettandGitHub 11205411bb Fix crash when writablity becomes false and races against finishing the http request (#768)
### Motivation

If the channel's writability changed to false just before we finished a
request, we currently run into a precondition.

### Changes

- Remove the precondition and handle the case appropiatly

### Result

A crash less.
2024-09-03 13:54:44 +02:00
Fabian FettandGitHub 776a1c2304 Fix NIO deprecations after update to 2.71.0 (#769)
`NIOTooManyBytesError` now requires the `maxBytes` in its initializer.
2024-09-03 13:36:24 +02:00
1290119b31 Assume http2 connection by default, instead of http1 (#758)
Since most of the servers now conform to http2, the change here updates
the behaviour of assuming the connection to be http2 and not http1 by
default. It will migrate to http1 if the server only supports http1.
One can set the `httpVersion` in `ClientConfiguration` to `.http1Only`
which will start with http1 instead of http2.

Additional Changes:

- Fixed an off by one error in the maximum additional general purpose
connection check
- Updated tests

---------

Co-authored-by: Ayush Garg <ayushgarg@apple.com>
Co-authored-by: David Nadoba <d_nadoba@apple.com>
Co-authored-by: Fabian Fett <fabianfett@apple.com>
2024-08-15 14:26:52 +02:00
aryan-25andGitHub 4b7a68e997 Fix OOM issue when setting concurrentHTTP1ConnectionsPerHostSoftLimit to Int.max (#763)
### Motivation:

When a user wishes to make the connection pool create as many concurrent
connections as possible, a natural way to achieve this would be to set
`.max` to the `concurrentHTTP1ConnectionsPerHostSoftLimit` property.

```swift
HTTPClient.Configuration().connectionPool = .init(
    idleTimeout: .hours(1),
    concurrentHTTP1ConnectionsPerHostSoftLimit: .max
)
```

The `concurrentHTTP1ConnectionsPerHostSoftLimit` property is of type
`Int`. Setting it to `Int.max` leads to `Int.max` being passed as an
argument to `Array`s `.reserveCapacity(_:)` method, causing an OOM
issue.

Addresses Github Issue #751 

### Modifications:

Capped the argument to `self.connections.reserveCapacity(_:)` to 1024 in
`HTTPConnectionPool.HTTP1Connections`

### Result:

Users can now set the `concurrentHTTP1ConnectionsPerHostSoftLimit`
property to `.max` without causing an OOM issue.
2024-08-14 11:56:26 +02:00
Cory BenfieldandGitHub 07f171bed7 Avoid using deprecated API in tests (#762)
This gets CI working again
2024-08-07 07:49:48 -07:00
aryan-25andGitHub 54d1006dc9 Add leading slash in relative URL requests if necessary (#747) 2024-07-09 12:47:07 +02:00
aryan-25andGitHub 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-25andGitHub 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
e27aef494d Make ConnectionPool's retryConnectionEstablishment public (#744)
* Make ConnectionPool's `retryConnectionEstablishment` public

* Unified tests to consistently use `enableFastFailureModeForTesting()`

* Add `retryConnectionEstablishment` as optional parameter to the initializer of `HTTPClient.Configuration.ConnectionPool`

* Reverted change to initializer to prevent API stability breakage

* Add parameterless initializer for `HTTPClient.Configuration.ConnectionPool`

* Moved default values for `HTTPClient.Configuration.ConnectionPool` to the property declarations, so they only have to be specified at one point

* Removed superfluous spaces

Co-authored-by: Cory Benfield <lukasa@apple.com>

* Re-added missing line break

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2024-06-18 14:04:29 +01:00
Gustavo CairoandGitHub a22083713e Disable SETTINGS_ENABLE_PUSH HTTP/2 setting (#741) 2024-05-01 12:49:09 +01:00
hamzahrmalikandGitHub fb308ee72f Move availability guard to correct test (#734)
It was previously accidentally moved to a different test, which does not need it
Async tests need the guard for macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0
2024-04-05 11:16:39 +01:00
e0977cf290 HTTPClient.shared a globally shared singleton & .browserLike configuration (#705)
Co-authored-by: Johannes Weiss <johannes@jweiss.io>
2024-04-03 05:54:00 -07:00
hamzahrmalikandGitHub 36292f9d57 Renew certificates in tests (#731) 2024-03-29 01:12:13 -07:00
Gustavo CairoandGitHub 83f015bf94 Fix write timeout not being initialised (#730) 2024-03-21 16:18:22 +00:00
Alastair HoughtonandGitHub 09b7eb751e Add support for Musl. (#726)
Motivation:

We would like to make this work for Musl so that we can build fully
statically linked binaries that use AsyncHTTPClient.

Modifications:

Define `_GNU_SOURCE` as a compiler argument; doing it in a source file
doesn't work properly with modular headers.

Add imports of `Musl` in appropriate places.

`Musl` doesn't have `strptime_l`, so avoid using that.

Result:

async-http-client will build for Musl.
2024-01-19 16:09:35 -08:00
Gustavo CairoandGitHub 5ccda442f1 Use the given connection pool idle timeout in the HTTPClient.Configuration inits (#723) 2023-12-21 09:51:54 -03:00
Si BeaumontandGitHub a4904fcc6b Add missing availability guards in tests (#719)
## Motivation

Some of the test code was missing availability guards for Apple platforms, resulting in build failures for these platforms, e.g.

```
error: 'AsyncSequence' is only available in iOS 13.0 or newer
```

## Modifications

Add missing availability guards. I've tried to keep them as scoped as possible.

## Result

Tests can now build for run on iOS and other Apple platforms.
2023-12-18 04:52:50 -08:00
Gustavo CairoandGitHub d2d35663a2 Add an idle write timeout (#718) 2023-12-18 09:06:06 -03:00
Peter AdamsandGitHub c70e085679 testPlatformConnectErrorIsForwardedOnTimeout port reuse (#716)
Motivation:

The above test has been seen to fail with port already in use.
The test assumes that a port can be bound to twice in a row.
It's possible that another process takes the port between the two
binds - this can be stopped by binding a second time before stopping
the first.

Modifications:

Allow port reuse and reorder the test to bind a second time before
releasing the first.

Result:

Test should no longer be flaky.
2023-11-03 06:58:47 -07:00
Johannes WeissandGitHub d766674c7e HTTPClientRequest: allow custom TLS config (#709) 2023-10-16 07:00:58 -07:00
David NadobaandGitHub 4c07d3bbf6 Fix flaky test TransactionTests.testCancelAsyncRequest (#707)
* Fix flaky test `TransactionTests.testCancelAsyncRequest`

Resolves #706.
The continuation is resumed with the cancelation error before we cancel the scheduled request.
https://github.com/swift-server/async-http-client/blob/62c06d47c8d21c91335e9f8998589e4ce31411e6/Sources/AsyncHTTPClient/AsyncAwait/Transaction.swift#L290C10-L294

Therefore this test is inherently flaky. The fix waits up to one second for the scheduled request to be canceled.

* self.fulfillment(of:) is not available on Linux

* Fix formatting

* Fix 5.6
2023-10-04 19:47:57 +02:00
Rick Newton-RogersandGitHub 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 NadobaandGitHub 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
16f7e62c08 Add unit tests for NWWaitingHandler, closes #589 (#702)
* Add unit tests for NWWaitingHandler

Motivation:

Closes #589. Since we already have a public initializer for
NIOTSNetworkEvents.WaitingForConnectivity, we should add unit tests for
the handler now that it's straightforward.

Modifications:

The tests are in their own file `Tests/NWWaitingHandlerTests.swift`.

* Bump swift-nio-transport-services to 1.13.0

* SwiftFormat@0.48.8

* Apply suggestions from code review

Co-authored-by: David Nadoba <dnadoba@gmail.com>

---------

Co-authored-by: David Nadoba <dnadoba@gmail.com>
2023-08-14 12:28:11 -07:00
8c90405f0c use NIOSingletons EventLoops/NIOThreadPool instead of spawning new (#697)
Co-authored-by: Johannes Weiss <johannes@jweiss.io>
2023-08-14 14:59:33 +01:00
Cory BenfieldandGitHub 62c06d47c8 Remove tests relying on OS-dependent behaviour (#703)
Motivation

URL parsing has changed in macOS Sonoma and associated releases. Our
tests were reliant on the old behaviour. The behaviour is controlled
by the OS on which the program was linked, which makes it impossible
for us to programmatically work out which result we should see.

The affected tests are not actually useful, we don't really care how
the URLs parse, so we can safely just remove them.

Modifications

Remove the affected tests.

Result

Tests pass!
2023-08-10 03:33:18 -07:00
David NadobaandGitHub e1c85a65d8 Add timeout to RequestBagTests.testCancelFailsTaskAfterRequestIsSent test (#699)
We have seen that the `RequestBagTests.testCancelFailsTaskAfterRequestIsSent` can timeout the CI. To better understand where it fails we can add a timeout that will throw with a timeout error and fail the error check below it. This will make will allow us in the future to better analyse the failure and will no longer timeout the CI.
2023-07-14 11:34:27 +01:00
David NadobaandGitHub 7935de10c0 Fix flaky AsyncAwaitEndToEndTests.testImmediateDeadline test (#698) 2023-07-14 10:01:30 +01:00
brennoandGitHub df66c67cad Fixed typo (#695) 2023-06-30 12:18:05 +02:00
David NadobaandGitHub 78db67e5bf Tolerate new request after connection error happened (#688)
* Tolerate new request after connection error happened

* fix tests
2023-05-17 09:37:35 +01:00
David NadobaandGitHub d62c475401 Drop Swift 5.5 (#686) 2023-04-14 17:05:09 +01:00
David NadobaandGitHub b9029ef67c Add support for custom cancellation error (#683) 2023-04-13 17:00:03 +01:00
David NadobaandGitHub e18db27dd3 Replace TransactionBody with NIOAsyncSequenceProducer (#677)
* save progress

* Replace `TransactionBody` with `NIOAsyncSequenceProducer`

* test

* revert unnesscary changes

* Add end-to-end test

which currently fails because of https://github.com/apple/swift-nio/issues/2398

* soundness

* Use latest swift-nio release

* throw CancellationError on task cancelation

* Fix Swift 5.5 & 5.6
2023-04-12 15:11:56 +01:00
George BarnettandGitHub 6c5058ee2c Add a control to limit connection reuses (#678)
Motivation:

Sometimes it can be helpful to limit the number of times a connection
can be used before discarding it. AHC has no such support for this at
the moment.

Modifications:

- Add a `maximumUsesPerConnection` configuration option which defaults
  to `nil` (i.e. no limit).
- For HTTP1 we count down uses in the state machine and close the
  connection if it hits zero.
- For HTTP2, each use maps to a stream so we count down remaining uses
  in the state machine which we combine with max concurrent streams to
  limit how many streams are available per connection. We also count
  remaining uses in the HTTP2 idle handler: we treat no remaining uses
  as receiving a GOAWAY frame and notify the pool which then drains the
  streams and replaces the connection.

Result:

Users can control how many times each connection can be used.
2023-04-11 14:49:44 +01:00
91b26407ad Update collect to use content-length to make early checks
Motivation:
not accumulate too many bytes

Modifications:
Implementing collect function to use NIOCore version to prevent overflowing

Co-authored-by: Cory Benfield <lukasa@apple.com>
2023-04-04 16:56:58 +01:00
David NadobaandGitHub 98b45ed1cd Allow DNS override (#675)
Sometimes it can be useful to connect to one host e.g. `x.example.com` but request and validate the certificate chain as if we would connect to `y.example.com`. This is what this PR adds support for by adding a `dnsOverride` configuration to `HTTPClient.Configuration`. This is similar to curls `—resolve-to` option but only allows overriding host and not ports for now.
2023-03-30 08:21:41 +01:00
Cory BenfieldandGitHub 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 FettandGitHub e26459902c Fix HTTP2StreamChannel leak (#657)
* Fix HTTP2StreamChannel leak

* Update code comments.
2023-02-14 10:04:27 +01:00
1d24271fee Fix crash for large HTTP request headers (#661)
* Reproducer

* Refactor test case

* Refactor tests

* Remove debugging artefacts

* Fix typo

* Fix formatting

* Remove `promise?.succeed(())`

* Add test for HTTP2 request with large header

Motivation

We currently don't handle large headers well which trigger a channel writability change event.

Modification

Add failing (but currently skipped) tests which reproduces the issue
Result

We can reliably reproduce the large request header issue in an integration and unit test.
Note that the actual fix is not included to make reviewing easier and will come in a follow up PR.

* Remove logging

* Fix crash for large HTTP request headers

Fix crash for when sending HTTP request headers result in a channel writability change event

* Formatting and linux tests

* Formatting and linux tests

* Generate linux tests

* Use previous default max concurrent streams value of 10

* Fix crash if request is canceled after request header is send

* generate linux tests and run swift format

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2023-02-10 15:41:26 +01:00
David NadobaandGitHub aa66da80fa Fix request head continuation misuse (#666)
* Fix request head continuation misuse

Fixes #664

* remove unused function

* format & generate linux tests
2023-02-10 14:13:21 +00:00
Fabian FettandGitHub f65f45b727 Fix Request streaming memory leak (#665) 2023-02-07 17:18:56 +01:00
David NadobaandGitHub 59bfb96afb Add test for HTTP2 request with large header (#659)
Motivation

We currently don't handle large headers well which trigger a channel writability change event.

Modification

Add failing (but currently skipped) tests which reproduces the issue
Result

We can reliably reproduce the large request header issue in an integration and unit test.
Note that the actual fix is not included to make reviewing easier and will come in a follow up PR.
2023-01-26 14:26:58 +01:00
David NadobaandGitHub 67f99d1798 Add test for HTTP1 request with large header (#658)
* Reproducer

* Refactor test case

* Refactor tests

* Remove debugging artefacts

* Fix typo

* Fix formatting

* Remove `promise?.succeed(())`

* Rename `onRequestCompleted` to `onConnectionIdle`
2023-01-26 11:11:30 +00:00
David NadobaandGitHub 5daaa38ba1 Add Swift 5.8 CI and update nightly CI to Ubuntu 22.04 (#655)
* Add Swift 5.8 CI

* Update nightly CI to Ubuntu 22.04

* Fix warnings in test target with latest NIO release

Replace calls to `.wait()` with calls to `.get()`
2023-01-18 10:29:51 +00:00
Cory BenfieldandGitHub 7f05a8da46 Merge pull request from GHSA-v3r5-pjpm-mwgq
Motivation

Allowing arbitrary data in outbound header field values allows for the
possibility that users of AHC will accidentally pass untrusted data into
those values. That untrusted data can substantially alter the parsing
and content of the HTTP requests, which is extremely dangerous. The
result of this is vulnerability to CRLF injection.

Modifications

Add validation of outbound header field values.

Result

No longer vulnerable to CRLF injection
2023-01-17 11:06:08 +00:00