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.
### Motivation:
A performance test executing 100,000 sequential requests against a
simple
[`NIOHTTP1Server`](https://github.com/apple/swift-nio/blob/main/Sources/NIOHTTP1Server/README.md)
revealed that 7% of total run time is spent in the setter of the
`request` property in `HTTP1ClientChannelHandler` (GitHub Issue #754).
The poor performance comes from [processing the string interpolation
`"\(self.eventLoop)"`](https://github.com/swift-server/async-http-client/blob/6df8e1c17e68f0f93de2443b8c8cafca9ddcc89a/Sources/AsyncHTTPClient/ConnectionPool/HTTP1/HTTP1ClientChannelHandler.swift#L39C17-L39C75)
which under the hood calls a computed property.
This problem can entirely be avoided by storing `eventLoop.description`
when initializing `HTTP1ClientChannelHandler`, and using that stored
value in `request`'s setter, rather than computing the property each
time.
### Modifications:
- Created a new property `let eventLoopDescription:
Logger.MetadataValue` in `HTTP1ClientChannelHandler` that stores the
description of the `eventLoop` argument that is passed into the
initializer.
- Replaced the string interpolation `"\(self.eventLoop)"` in `request`'s
setter with `self.eventLoopDescription`.
### Result:
`HTTP1ClientChannelHandler.eventLoop`'s `description` property is cached
upon initialization rather than being computed each time in the
`request` property's setter.
---------
Co-authored-by: Cory Benfield <lukasa@apple.com>
### 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.
* 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>
Motivation
If we receive an early HTTP response, the last action on a HTTP/1.1
connection is to send the .end message. While we had an error handling
path in the code, it wasn't tested, and when executed it would end up
leaking the connection by failing to close it _or_ return it to the
pool.
This patch fixes the issue by appropriately terminating the connection
and adding a test.
Modifications
Add a test
Terminate the connection if sendEnd fails
Result
Fewer connection leaks
Motivation
When users stream their bodies they may still want to send Connection:
close headers and terminate the connection early. This should work
properly.
Unfortunately it became clear that we didn't correctly pass the
information that the connection needed to be closed. As a result, we'd
inappropriately re-use the connection, potentially causing unnecessary
HTTP errors.
Modifications
Signal whether the connection needs to be closed when the final
connection action is to send .end.
Results
We behave better with streaming uploads.
Motivation
It's totally acceptable for a HTTP server to respond before a request
upload has completed. If the response is an error, we should abort the
upload (and we do), but if the response is a 2xx we should probably just
finish the upload.
In this case it turns out we'll actually hit a crash when we attempt to
deliver an empty body message. his is no good!
Once that bug was fixed it revealed another: while we'd attempted to
account for this case, we hadn't tested it, and so it turns out that
shutdown would hang. As a result, I've also cleaned that up.
Modifications
- Tolerate empty circular buffers of bytes when streaming an upload.
- Notify the connection that the task is complete when we're done.
Result
Fewer crashes and hangs.
### Motivation
Today `didSendRequestPart` is called after a request body part has been passed to the executor. However, this does not mean that the write hit the socket. Users may depend on this behavior to implement back-pressure. For this reason, we should only call this `didSendRequestPart` once the write was successful.
### Modification
Pass a promise to the actual channel write and only call the delegate once that promise succeeds.
### Result
The delegate method `didSendRequestPart` is only called after the write was successful. Fixes#565.
Co-authored-by: Fabian Fett <fabianfett@apple.com>
Same fix for HTTP/1 that landed for HTTP/2 in #558.
### Motivation
`HTTP1ClientChannelHandler` currently does not tolerate immediate write errors.
### Changes
Make `HTTP1ClientChannelHandler` resilient to failing writes.
### Result
Less crashes in AHC HTTP/1.
Swift tools version 5.3 and higher (the version that is specified at very top of a Package.swift file) excludes folders with a dot in the name by default. It luckily produces a warning "found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target". However, this issue is buried under a lot of missing types Errors because of the 3 excluded files.
I run into this issue and it took me some time to figure out what the actual problem was. As we will eventually move from 5.2 to 5.3 we can already save the next person some time by resolving this issue now.