Commit Graph

82 Commits

Author SHA1 Message Date
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 f17a47e916 Allow immediate request failure on connection error (#625) 2022-10-10 13:34:42 +01:00
Fabian Fett 4d69c84617 Add Hashable conformance to HTTPClient.Configuration.HTTPVersion (#636) 2022-10-07 08:15:14 -07: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
Johannes Weiss 7f998f5118 add a future-returning shutdown method (#626)
Co-authored-by: Johannes Weiss <johannes@jweiss.io>
2022-09-07 06:12:05 -07:00
David Nadoba c3c90aab58 Adopt Sendable (#621) 2022-08-25 11:45:13 +02:00
Karl 18109d842d Use NIOCore.System.coreCount for the fileIO thread pool (#618) 2022-08-20 12:22:41 +01: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 e294c8f28f Accurately apply the connect timeout in async code (#616)
Motivation

We should apply the connect timeout to the complete set of connection
attempts, rather than the request deadline. This allows users
fine-grained control over how long we attempt to connect for. This is
also the behaviour of our old-school interface.

Modifications

- Changed the connect deadline calculation for async/await to match that
  of the future-based code.
- Added a connect timeout test.

Result

Connect timeouts are properly handled
2022-08-16 13:17:45 +01: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
Cory Benfield 0527bbb466 Remove the last remaining NIOAtomic (#607)
Motivation

Warnings aren't great, and NIOAtomic is deprecated.

Modifications

Replace the last use of NIOAtomic with ManagedAtomic.

Result

Fewer warnings
Fixes #606
2022-08-03 10:02:20 +01:00
David Nadoba 14fa6d944d Report last connection error if request deadline is exceeded (#601) 2022-07-01 10:39:38 +02:00
Cory Benfield 3fcd67061f Improve errors and testing using NIOTS (#588)
Motivation

Currently error reporting with NIO Transport Services is often sub-par.
This occurs because the Network.framework connections may enter the
waiting state until the network connectivity state changes. We were not
watching for the user event that contains the error in that state, so if
we timed out in that state we'd just give a generic timeout error,
instead of telling the user anything more detailed.

Additionally, several of our tests assume that failure will be fast, but
in NIO Transport Services we will enter that .waiting state. This is
reasonable, as changed network connections may make a connection that
was not succeeding suddenly viable. However, it's inconvenient for
testing, where we're mostly interested in confirming that the error path
works as expected.

Modifications

- Add an observer of the WaitingForConnectivity event that records it
  into our state machine for later reporting.
- Add support for disabling waiting for connectivity for testing
  purposes.
- Add annotations to several tests to stop them waiting for
  connectivity.

Results

Faster tests, better coverage, better errors for our users.

Co-authored-by: David Nadoba <dnadoba@gmail.com>
2022-06-01 14:13:47 +01:00
Christian Priebe 89b0da2bf8 Add HTTPClientError shortDescription property (#583)
This adds a shortDescription property to HTTPClientError which provides a short
description of the error without associated values.
2022-04-22 07:59:58 +01:00
David Nadoba b1c0c3c77b replace EventLoopGroup.next() with .any() (#526) 2021-12-14 21:59:54 +01:00
David Nadoba bf5668c37b Use the current EventLoop as the requests preferred EventLoop (#515)
* Use the current `EventLoop` as the requests prefered `EventLoop` if possible

* use released version of swift-nio
2021-12-14 20:10:31 +01: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 9eaecbbbce SwiftFormat --ifdef no-indent (#494)
* SwiftFormat --ifdef no-indent

* update `generate_linux_tests.rb` to use new indention rule
2021-11-25 17:09:19 +01:00
David Nadoba 0ed00b8b36 Always overwrite Transport-Encoding and Content-Length headers (#479) 2021-11-23 10:22:57 +01:00
Fabian Fett ec2e080d70 Only crash in debug mode, if HTTPClient was not shutdown (#478)
### Motivation

Generally we want to inform users that they need to shutdown their HTTPClient. Until `1.6.0` we did this with an assert in HTTPClient's deinit. With `1.6.0` this behavior was raised to a precondition. Because of this adopters might suddenly crash in production where they didn't before.

### Changes

- This pr reverts the current behavior back to something pre `1.6.0`

### Result

- HTTPClient doesn't crash in production anymore.
2021-11-17 14:22:55 +01:00
David Nadoba 3e44e5154e [HTTP2] Make HTTPVersion public and set to .automatic by default (#473) 2021-11-11 14:41:11 +01:00
Fabian Fett 7617c35db3 Handle NIOSSLError.uncleanShutdown correctly (#472)
### Motivation

Fixes #238 and #231.

### Changes

- Extracted the unclean shutdown test from `HTTPClientTests` into their own file `HTTPClientUncleanSSLConnectionShutdownTests`
- Copy and pasted @weissi great explanation from #238 into the test file
- Removed property `ignoreUncleanSSLShutdown` everywhere

### Result

`ignoreUncleanSSLShutdown` on `HTTPClient.Configuration` is deprecated and ignored.

Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
2021-11-11 11:02:54 +01:00
Fabian Fett 170fd536f9 Support informational response heads (#469) 2021-11-10 13:33:38 +01:00
David Nadoba 60fef53db7 [HTTP2] Internal HTTPVersion configuration (#463) 2021-11-02 18:46:29 +00: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 16ad7588b1 [HTTP1Connection] Handle 101 Switching Protocols (#442) 2021-09-28 09:52:26 +02:00
Fabian Fett 2a47a1da75 [HTTPClient.Configuration] Make connection pool size configurable (#437) 2021-09-27 09:35:40 +02:00
Fabian Fett 2565dfe0dc [HTTPConnectionPool] Implementation switch (#427) 2021-09-24 09:28:09 +02:00
Fabian Fett fb49c1be5f Add new HTTPConnectionPool Manager (#420)
Co-authored-by: George Barnett <gbarnett@apple.com>
2021-09-10 17:25:41 +02:00
Fabian Fett 4d726bad8d Add ConnectionPool HTTP1StateMachine (#416) 2021-09-09 15:34:03 +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 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
Fabian Fett 8e4d51908d Refactor Channel creation (#377)
- The connection creation logic has been refactored into a number of smaller methods that can be combined
- Connection creation now has a logical home. It is moved from `Utils.swift` into a `ConnectionFactory`
- There are explicit `ChannelHandlers` that are used for connection creation:
  - `TLSEventsHandler` got its own file and unit tests
  - `HTTP1ProxyConnectHandler` got its own file and unit tests
  - `SOCKSEventsHandler` got its own file and unit tests
- Some small things are already part of this pr that will get their context later. For example: 
  - `HTTPConnectionPool` is added as a namespace to not cause major renames in follow up PRs
  - `HTTPConnectionPool.Connection.ID` and its generator were added now. (This will be used later to identify a connection during its lifetime)
  - the file `HTTPConnectionPool+Manager` was added to give `HTTPConnectionPool.Connection.ID.Generator` already its final destination.
2021-06-28 13:17:33 +02:00
David Evans 102b7e4bce Update NIO family dependencies to 5.2+ versions and fix deprecations (#381)
Updated:

NIO
NIOSSL
NIO Extras
NIOTS
Also fix TLSConfiguration.forClient() warnings by converting to TLSConfiguration.makeClientConfiguration(). Also the same for forServer().
2021-06-23 14:58:08 +01: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
Johannes Weiss e2d03ffb32 cache NIOSSLContext (saves 27k allocs per conn) (#362)
Motivation:

At the moment, AHC assumes that creating a `NIOSSLContext` is both cheap
and doesn't block.

Neither of these two assumptions are true.

To create a `NIOSSLContext`, BoringSSL will have to read a lot of
certificates in the trust store (on disk) which require a lot of ASN1
parsing and much much more.

On my Ubuntu test machine, creating one `NIOSSLContext` is about 27,000
allocations!!! To make it worse, AHC allocates a fresh `NIOSSLContext`
for _every single connection_, whether HTTP or HTTPS. Yes, correct.

Modification:

- Cache NIOSSLContexts per TLSConfiguration in a LRU cache
- Don't get an NIOSSLContext for HTTP (plain text) connections

Result:

New connections should be _much_ faster in general assuming that you're
not using a different TLSConfiguration for every connection.
2021-05-13 12:16:52 +01:00
Cory Benfield b075d19007 Unconditionally insert TLSEventsHandler (#349)
Motivation:

AsyncHTTPClient attempts to avoid the problem of Happy Eyeballs making
it hard to know which Channel will be returned by only inserting the
TLSEventsHandler upon completion of the connect promise. Unfortunately,
as this may involve event loop hops, there are some awkward timing
windows in play where the connect may complete before this handler gets
added.

We should remove that timing window by ensuring that all channels always
have this handler in place, and instead of trying to wait until we know
which Channel will win, we can find the TLSEventsHandler that belongs to
the winning channel after the fact.

Modifications:

- TLSEventsHandler no longer removes itself from the pipeline or throws
  away its promise.
- makeHTTP1Channel now searches for the TLSEventsHandler from the
  pipeline that was created and is also responsible for removing it.
- Better sanity checking that the proxy TLS case does not overlap with
  the connection-level TLS case.

Results:

Further shrinking windows for pipeline management issues.
2021-03-18 12:21:23 +00:00
Cory Benfield ae5f185907 Use synchronous pipeline hops to remove windows. (#346)
Motivation:

There is an awkward timing window in the TLSEventsHandler flow where it
is possible for the NIOSSLClientHandler to fail the handshake on
handlerAdded. If this happens, the TLSEventsHandler will not be in the
pipeline, and so the handshake failure error will be lost and we'll get
a generic one instead.

This window can be resolved without performance penalty if we use the
new synchronous pipeline operations view to add the two handlers
backwards. If this is done then we can ensure that the TLSEventsHandler
is always in the pipeline before the NIOSSLClientHandler, and so there
is no risk of event loss.

While I'm here, AHC does a lot of pipeline modification. This has led to
lengthy future chains with lots of event loop hops for no particularly
good reason. I've therefore replaced all pipeline operations with their
synchronous counterparts. All but one sequence was happening on the
correct event loop, and for the one that may not I've added a fast-path
dispatch that should tolerate being on the wrong one. The result is
cleaner, more linear code that also reduces the allocations and event
loop hops.

Modifications:

- Use synchronous pipeline operations everywhere
- Change the order of adding TLSEventsHandler and NIOSSLClientHandler

Result:

Faster, safer, fewer timing windows.
2021-03-16 09:41:55 +00:00
Artem Redkin 0a8dddbe15 Fixes default timeout documentation comment (#317)
Motivation:
Right now documentation states that timrout defaults to no timeout, this
is no actually true, if timeout is not set NIO bootstrap defaults to 10
seconds connect timeout.

Modifications:
Updates documentation comment.

Result:
Closes #118
2020-11-11 16:02:21 +00:00
Artem Redkin 236b1de5ad Fixes propagation of errors during TLS handshakre (#316)
Motivation:
Right now we only handle one type of SSL error: `.handshakeFailed`,
but in reality a multitude of errors can happen, for example, remote
party might just close connection that will in turn raise
`.uncleanShutdown` error, that will be dropped on the floor and
users will only get non-descriptive `NoResult` error.

Modifications:
Handle all types of SSL errors during handshake instead of just one.
Adds a test.

Result:
Closes #313

Co-authored-by: Cory Benfield <lukasa@apple.com>
2020-11-11 15:50:13 +00:00
Artem Redkin c9a9bf061d rename connection pool configuration (#288) 2020-07-31 10:06:53 +01:00
Artem Redkin f69b68ffa8 fail if user tries writing bytes after request is sent (#270) 2020-07-30 11:22:55 +01:00
Artem Redkin 2e6a64abb3 add a separate configuration struct for pool (#284)
* add a separate configuration struct for pool

* review fixes

* review fix
2020-07-17 16:06:11 +01:00
Adam Fowler 96a803e98a Use SwiftLogNoOpLogHandler from swift-log (#282)
Co-authored-by: Cory Benfield <lukasa@apple.com>
Co-authored-by: Artem Redkin <artem@redkin.me>
2020-07-17 09:47:23 +01:00
Adam Fowler 643a0dc249 Added default value for queue in HTTPClient.shutdown() (#279)
Default it to .global()
2020-06-29 13:26:06 +01:00
Max Desiatov dcf7e5c702 Fix invalid code in HTTPClient.swift doc comment (#271)
`HTTPClient(eventLoopGroupProvider = .createNew)` is not a valid Swift expression.
2020-06-24 08:13:30 +01:00
Artem Redkin 61a80a2d34 assume chunked on a stream with no length (#247)
Motivation:
Streams length parameter is optional to allow cases were stream length is not known in advance, but we do not support this in request validation. This PR aims to address that.

Modifications:
Modifies request validation to default to chunked encoding if body length is zero or to passed in content-length header
Adds a test

Result:
Closes #218
2020-06-23 16:42:16 +01:00
Artem Redkin aac4357b65 notify delegate about connect errors (#245) 2020-06-23 15:00:19 +01:00
Max Desiatov c4f5155384 Fix doc comment for redirectConfiguration (#266)
`redirectConfiguration` can't default to `false` as it's not a boolean value, and the default value is `RedirectConfiguration()`.

Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Co-authored-by: Artem Redkin <artem@redkin.me>
2020-06-22 17:39:58 +01:00