Commit Graph

90 Commits

Author SHA1 Message Date
Ilya Teterin 947429beb4 Address warning reported by thread safety analyzer (#319)
Motivation:

Thread safety analyzer reports warning about observable state
leaving lock guarded code blocks. This PR address some of the warnings.

Analysis of the warning does not prove that we have a real bug and all the
warnings are considered as potential bugs.

Analyzer used is:
`docker run --rm -v $(pwd):/src -w /src swift:5.3.1 swift test -c
release --sanitize=thread --enable-test-discovery`

Modifications:

* accessor to count of connections in connection pool is guarded by lock

Result:

Most of thread safety warnings are addressed without modification of observable
code behaviour.
2020-11-27 17:57:25 +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 1bc2e1ae23 add another expires date format (#315) 2020-11-11 15:43:44 +00:00
Ilya Teterin e401a2801c Fixes #234 by removing setter on internal ConnectionsState so modification (#311)
allowed only using exposed API.

Motivation:

Having a setter for internal state of ConnectionsState led to a subset
of test testing invalid invariants, for example when we have at the same
time an available connecion and a waiter, which is an invalid state of
the system.

Modifications:

* test of ConnectionsState
* ConnectionsState
* ConnectionPool

are modified so the state under tests is achieved only by a sequence of
modifications invoked by state API.

During modification some tests are eliminated as they were testing
artificial state, which can not be achieved by exposed APIs.

ConnectionsState is pruned from "replace" as in no valid state we can
have a situation when we can "replace" a connection.

Invalid invariants and tests are removed.

Result:

We do not have a way to modify state of the ConnectionsState by direct
interaction with private state of the object. Getter on the state is
considered harmless and used for tests only.
2020-10-02 14:31:25 +01:00
Ilya Teterin c65b2ae297 Code clean up to to fix issue #234 - ConnectionsState exposes a setter into internal state (#310)
* Introduce helper methods for test of ConnectionsState

Motivation:

Issue #234 highlights that we directly manipulate ConnectionsState and
this commit prepares tests to be refactored to manipulate the state
by exposed APIs instead.

Modifications:

* introduce helper methods in ConnectionPoolTestsSupport.swift

Result:

* no observable changes

* Move Connection tests out of ConnectionsState tests into separate file.

Motivation:

Clean up of code to address issue #234 - here we move away
connection tests to separate files outside of ConnectionsState tests
so we will be able to work on the ConnectionsState in focussed mode.

Modifications:

Connection tests moved to separate files.

Result:

No observable changes.

* Gather Connection code into Connection.swift

Motivation:

For tests we will need a simple version of Connection, so here I gather
Connection code in one place and will generify ConnectionsState on next
commit.

Modifications:

Code of Connection is moved from multiple files into single
Connections.swift.

Result:

All tests are passing, no observable behaviour change.

* Introduce generic type ConnectionType into ConnectionsState

Motivation:

To rework tests of ConnectionsState we want to have a "simpler" version
of Connection to be used, therefore here we convert ConnectionsState to
support generic type ConnectionType. We will substitute current
Connection with a test version in follow up commit.

Modifications:

ConnectionsState is altered to work on generic type ConnectionType
instead of solid type Connection.

Users of ConnectionsState are modified to provide type Connection into
ConnectionType in this commit.

Result:

Test are passing, no observable behaviour change.
2020-09-30 17:03:52 +01:00
Max Desiatov 49a0d30fa3 Add FileDownloadDelegate for simple file downloads (#275)
* Add FileDownloadDelegate for simple file downloads

* Add testFileDownload to the allTests array

* Fix formatting

* Fix compatibility with Swift 5.0

* Add doc comments, update README.md

* Refine FileDownloadDelegate description in README

* Bump NIO version, remove weak self, cleanup test

* Fix formatting issues in a doc comment

* Create separate Progress struct, async open file

* Create an ad-hoc EventLoopGroup for opening a file

* Move file opening code to `didReceiveBodyPart`

* Fix linter error in FileDownloadDelegate.swift

* Fix wrong future assignment in FileDownloadDelegate

* Fix Swift 5.0 return statement compatibility

* Fix linter warning

* Fix Swift 5.0 return statement compatibility

* Remove redundant `write` function

* Add negative test case and separate testing endpoint

* Add missing testFileDownloadError to the manifest
2020-09-10 08:30:19 +01:00
Fabian Fett 2a22156ef9 Use assertInEventLoop over assert(el.inEventLoop) (#303) 2020-09-08 09:14:30 +01:00
Artem Redkin 4b4d6605aa Fix state reverting (#298)
* fail if we get part when state is endOrError

* Prevent TaskHandler state change after `.endOrError`

Motivation:
Right now if task handler encounters an error, it changes state to
`.endOrError`. We gate on that state to make sure that we do not
process errors in the pipeline twice. Unfortunately, that state
can be reset when we upload body or receive response parts.

Modifications:
Adds state validation before state is updated to a new value
Adds a test

Result:
Fixes #297
2020-08-24 11:28:28 +01:00
Artem Redkin ffcd1e1a1c Fixes double-release of a connection. (#295)
Motivation:
TaskHandler unconditionally releases it's connection on error,
this can lead to double release. This issue actually indicates
a more general issue where handler continues to handle errors
even after its state is `.endOrError`. We need to fix this by
ignoring all subsequent errors.

Modifications:
1. Check state before calling out delegate and pool
2. Replace all error callouts with call to `errorCaught`

Result:
Fixes #294
2020-08-20 15:35:06 +01:00
Tim Condon 1432843305 Fix typo in Task<Response> (#293) 2020-08-20 12:12:18 +01: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
Dimitri Bouniol 5c7a317f5b Fixed an issue where redirects to socket path-based servers from any server was always allowed (#259)
* Added tests that ensure redirects to unix socket paths from a regular HTTP server are disallowed.

Motivation:

Currently, redirects to any supported URL scheme will always be allowed, despite code being in place to seemingly prevent it. See #230.

Modifications:

- Added a method to HTTPBin to redirect to the specified target.
- Added failing tests that perform redirects from a regular server to a socket-based server and vice versa.

Result:

Failing tests that show that the existing redirect checks were inadequate.

* Fixed an issue where redirects to socket path-based servers from any server was always allowed.

Motivation:

An arbitrary HTTP(S) server should not be able to trigger redirects, and thus activity, to a local socket-path based server, though the opposite may be a valid scenario. Currently, requests in either direction are allowed since the checks don't actually check the destination scheme.

Modifications:

- Refactored `hostSchemes`/`unixSchemes` to `hostRestrictedSchemes`/`allSupportedSchemes`, which better describes what they do.
- Refactored `Request.supports()` to `Request.supportsRedirects(to:)` since it is only used by Redirects now.
- Check the destination URL's scheme rather than the current URL's scheme when validating a redirect.

Result:

Closes #230

Co-authored-by: Artem Redkin <artem@redkin.me>
2020-06-22 17:56:01 +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
Artem Redkin afe6ae4226 fix missing connect timeout and make tests safer (#267)
* fix missing connect timeout and make tests safer

* swiftformat and linux tests

* fix timeout test

* speedup another test

* make tests safer
2020-06-22 16:19:16 +01:00
Artem Redkin aec3fee769 All internal connection flow should be executed when shutting down (#268) 2020-06-22 16:11:28 +01:00
Artem Redkin c097c17e3e fix flaky testContentLengthTooLongFails test (#269) 2020-06-22 15:42:37 +01:00
Dimitri Bouniol ec48f4f114 Convenience methods for socket paths (#235)
* Added additional tests for socketPath-based requests

Motivation:

While going through the existing tests, I identified a few more instances where we could add some testing.

Modifications:

Added one test that verifies Requests are being decoded correctly, and improved three others to check for path parsing, error throwing, and schema casing respectively.

Result:

Tests that continue to pass, but that will also catch any incompatible changes in the future.

* Added some convenience initializers to URL and methods to Request for making requests to socket paths

Motivation:

Creating URLs for connecting to servers bound to socket paths currently requires some additional code to get exactly right. It would be nice to have convenience methods on both URL and Request to assist here.

Modifications:

- Refactored the get/post/patch/put/delete methods so they all call into a one line execute() method.
- Added variations on the above methods so they can be called with socket paths (both over HTTP and HTTPS).
- Added public convenience initializers to URL to support the above, and so socket path URLs can be easily created in other situations.
- Added unit tests for creating socket path URLs, and testing the new suite of convenience execute methods (that, er, test `HTTPMETHOD`s). (patch, put, and delete are now also tested as a result of these tests)
- Updated the read me with basic usage instructions.

Result:

New methods that allow for easily creating requests to socket paths, and passing tests to go with them.

* Removed some of the new public methods added for creating a socket-path based request

Motivation:

I previously added too much new public API that will most likely not be necessary, and can be better accessed using a generic execute method.

Modifications:

Removed the get/post/patch/put/delete methods that were specific to socket paths.

Result:

Less new public API.

* Renamed execute(url:) methods such that the HTTP method is the first argument in the parameter list

Motivation:

If these are intended to be general methods for building simple requests, then it makes sense to have the method be the first parameter in the list.

Modifications:

Moved the `method: HTTPMethod` parameter to the front of the list for all `execute([...] url: [...])` methods, and made it default to .GET. I also changed the url parameter to be `urlPath` for the two socketPath based execute methods.

Result:

A cleaner public interface for users of the API.

* Fixed some minor issues introduces with logging

Motivation:

Some of the convenience request methods weren't properly adapted for logging.

Modifications:

- Removed a doc comment from patch() that incorrectly referenced a logger.
- Fixed an issue where patch() would call into post().
- Added a doc comment to delete() that references the logger.
- Tests for the above come in the next commit...

Result:

Correct documentation and functionality for the patch() and delete() methods.

* Updated logging tests to also check the new execute methods

Motivation:

The logging tests previously didn't check for socket path-based requests.

Modifications:

Updated the `testAllMethodsLog()` and `testAllMethodsLog()` tests to include checks for each of the new `execute()` methods.

Result:

Two more tests that pass.
2020-06-19 10:51:03 +01:00
Johannes Weiss 8e60b94178 use standard ByteBuffer construction methods (#262) 2020-06-17 15:48:11 +01:00
Artem Redkin 606ab0eaea check body length (#255) 2020-06-16 09:17:09 +01:00
Adam Fowler 785ced571c The host header should also include the port (#237)
See https://tools.ietf.org/html/rfc7230#section-5.4

If port is not 80 or 443 then add to host header.
Fixed up tests
2020-06-15 15:46:29 +01:00
Artem Redkin a61b31c954 fix test and a crash when closed (#254) 2020-06-15 12:24:08 +01:00
Artem Redkin bb8c4fadda Refactor provider shutdown and pending flows (#240) 2020-06-13 11:20:51 +01:00
Johannes Weiss 86db162a11 logging support (#227)
Motivation:

AsyncHTTPClient is not a simple piece of software and nowadays also
quite stateful. To debug issues, the user may want logging.

Modification:

Support passing a logger to the request methods.

Result:

Debugging simplified.
2020-06-09 15:55:23 +01:00
Dimitri Bouniol 364d1069a4 Better support for UNIX Domain sockets (#228)
* Added tests for http+unix and https+unix url schemes

Motivation:

Using a base URL as the socket path only works when the URL object is maintained as long as possible through the stack. Additionally, it doesn't currently provide a way to use TLS over UNIX sockets.

Modifications:

Added two tests to test out the to-be supported URL schemes, http+unix, and https+unix, which encode the socket path as a %-escaped hostname, as some existing services already do.

Result:

Better UNIX domain socket support.
2020-06-02 15:22:20 +01:00
Johannes Weiss 070c1e5f37 cpool: don't reuse connection if we sent close (#225)
Motivation:

Previously, we'd only use the server's connection header to determine if
we should close the connection or not. That's wrong because if we set
`connection: close` ourselves, we must not reuse again.

Modification:

Set `TaskHandler.closing = false` if we send a close header.

Result:

More HTTP correctness.
2020-05-21 15:43:38 +01:00
Artem Redkin f81d0fec12 draft for streaming el fixes (#215) 2020-05-20 15:09:49 +01:00
Artem Redkin ce82178164 fix validation error propagation (#221) 2020-05-20 11:50:13 +01:00
Artem Redkin 8adfdb9bc5 refactor pool (#192) 2020-05-18 17:47:21 +01:00
Fabian Fett b72756af52 Typo fix: Trasfer-Encoding -> Transfer-Encoding (#211) 2020-05-15 14:30:00 +01:00
Artem Redkin 0fbfdcc9f0 fix malformed cookie parsing (#210) 2020-05-13 18:31:36 +01:00
Artem Redkin 75a04337d9 allow empty value cookies (#208) 2020-05-13 09:41:26 +01:00
Artem Redkin f8b8de198c make cookie parsing case insensitive (#207) 2020-05-13 09:34:50 +01:00
Adam Fowler 5298f20331 Support NIO Transport Services - part 2 (#184)
This is the continuation of the good work of @Yasumoto and @weissi in #135

The following code adds support for NIO Transport services. When the ConnectionPool asks for a connection bootstrap it is returned a NIOClientTCPBootstrap which wraps either a NIOTSConnectionBootstrap or a ClientBootstrap depending on whether the EventLoop we are running on is NIOTSEventLoop.

If you initialize an HTTPClient with eventLoopGroupProvider set to .createNew then if you are running on iOS, macOS 10.14 or later it will provide a NIOTSEventLoopGroup instead of a EventLoopGroup.

Currently a number of tests are failing. 4 of these are related to the NIOSSLUncleanShutdown error the others all seem related to various race conditions which are being dealt with on other PRs. I have tested this code with aws-sdk-swift and it is working on both macOS and iOS.

Things look into:

The aws-sdk-swift NIOTS HTTP client had issues with on Mojave. We should check if this is the case for async-http-client as well.

Co-authored-by: Joe Smith <yasumoto7@gmail.com>
Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
2020-04-18 14:17:46 +01:00
Iain Smith be517e3cc1 Enable clients to call URLs that include %2F as an escaped backslash (#201)
* Enable clients to call URLs that include %2F as an escaped backslash

Previously `percentEncodedPath` was using `path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)`
which converts %2F to a literal '/'. This prevented users fetching URLs like https://api.travis-ci.org/repo/github/rails%2Frails
which use %2F as part of a path segment.

Migrating to `URLComponents(url: self, resolvingAgainstBaseURL: false)?.percentEncodedPath` has the desired behaviour
for the couple of test cases that exist.

Updated the test server to switch on the `percentEncodedPath` so it's easier
to understand the desired behaviour.
2020-04-15 11:24:30 +01:00
Fabian Fett 2d88de3eb6 Verify header field names (#191)
* HTTPRequest without body: Content-Length shall not be send
* Verify field names comply with RFC7230
2020-04-01 16:48:01 +01:00
Artem Redkin 2fcf0a9fdd fix location header lookup (#186) 2020-03-31 09:56:44 +01:00
Artem Redkin a6d1ebe302 Implement asynchronous shutdown (#183) 2020-03-30 13:23:34 +01:00
Artem Redkin 7211025f2a add version to response (#182)
* add version to response

* fix API breakage by deprecating old init

* review fix: use renamed instead of message
2020-03-26 16:46:59 +00:00
Trevör 38bef7c546 Fix leaked TLS handshake promise (#180) (#180)
motivation:
TLS handshake promise was leaked in some cases of failure (see #179)

changes:
- Avoid leaking promise
- Clearer completion flow for related futures
- Add testAvoidLeakingTLSHandshakeCompletionPromise test
2020-03-12 18:37:19 +00:00
Trevör 9cdd1dc389 Close idle pool connections (#170)
* Close idle pool connections

Motivation: Pooled connections should close at some point (see #168)

Changes:
- Add new poolingTimeout property to HTTPClient.Configuration, it's
default value is .seconds(60), it can be set to nil if one wishes to
disable this timeout.
- Add relevant unit test

Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
2020-03-03 21:51:50 +00:00
Trevör 473c51890f Remove unneeded assertion (#169)
* Remove activity assertion in prepareForClose

motivation: assertion on activity sometimes fails but it turns out it is overly restrictive

changes:
- remove assertion and accept any given activity in prepareForClose

* test closing connections whilst syncShutdown

Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
2020-02-27 15:37:33 +00:00
Trevör 19e2ea727e Add an HTTP/1.1 connection pool (#105)
motivation: Better performance thanks to connection reuse

changes:
- Added a connection pool for HTTP/1.1
- All requests automatically use the connection pool
- Up to 8 parallel connections per (scheme, host, port)
- Multiple additional unit tests
2020-02-25 15:43:16 +00:00