### Motivation:
To ensure NIOHTTP1 concurrency safety.
### Modifications:
* Enable strict concurrency checking in the package manifest.
* Mark several objects `Sendable` with `@preconcurrency` annotations
where they are returned in futures which may execute in arbitrary
concurrency domains.
* `NIOTypedHTTPClientProtocolUpgrader`
* `NIOTypedHTTPClientUpgradeConfiguration`
* `NIOUpgradableHTTPServerPipelineConfiguration`
* `NIOUpgradableHTTPClientPipelineConfiguration`
* `NIOTypedHTTPServerProtocolUpgrader`
* `NIOTypedHTTPServerUpgradeConfiguration`
* Mark handlers as explicitly not sendable
* `NIOTypedHTTPClientUpgradeHandler`
* `NIOTypedHTTPServerUpgradeHandler`
* Added new Sendable type aliases:
* `NIOHTTPClientUpgradeSendableConfiguration`
* `NIOHTTPServerUpgradeSendableConfiguration`
### Result:
No more concurrency warnings. Builds will warn and CI will fail if
regressions are introduced.
Adds a new `ChannelPipeline.SynchronousOperations.Position` type to fill
a hole in the API that prevented non-sendable Channel handlers being
added at a position to the pipeline via the synchronous operations.
---------
Co-authored-by: Cory Benfield <lukasa@apple.com>
### Motivation:
Documentation checking catches more issues in Swift 6.0.
### Modifications:
Adopt the Swift 6.0 image and fix the errors.
### Result:
More accurate docs.
* Apply formatting
* Apply no block comments rule
* Apply OmitExplicitReturns
* Apple OnlyOneTrailingClosureArgument
* Apply NoAssignmentInExpressions
* Fix up DontRepeatTypeInStaticProperties lint errors
* Apply `OrderedImports`
* Apply `ReplaceForEachWithForLoop`
* format file
* Enable the formatting pipeline
* Adopt `AmbiguousTrailingClosureOverload`
* Fix license header
* Fix format check
* Fix `EndOfLineComment`
* Fix CI
* Adapt CI script to check if changes when running formatting
* Separate lint and format into to steps
* Fix format
* Adopt `UseEarlyExits`
* Revert "Adopt `UseEarlyExits`"
This reverts commit d1ac5bbe12.
* Bump minimum Swift version to 5.7
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 integration test script
* Update docs
Result:
Remove support for Swift 5.6, add 5.10
* fix indentation issues
* 5.9 docker image use release image
Motivation:
Right now we always set the framing headers in HTTP requests and
responses that we send. This is a good practice for most users, but
it can cause issues, most notably in responses to CONNECT requests
which requires that we do not set framing headers.
Unfortunately, in NIO's current HTTP/1.1 design it is not possible
for us to suppress these headers. This is because the HTTP encoders
come _earlier_ in the pipeline than the decoders, so the HTTP
encoders do not know structurally what requests they are responding
to.
While we could merge the encoders/decoders, that's a fairly
substantial change. A better short-term change is to offer users
the ability to turn off the NIO header manipulation feature. In
this circumstance, users take on full responsibility for
appropriately framing their HTTP messages.
Modifications
- Add config to HTTPRequestEncoder and HTTPResponseEncoder.
- Plumb this config through.
- Add a bunch of tests.
Result
Users have way more control of HTTP/1.1 messages.
Motivation
HTTP headers are prevented from containing certain characters that can
potentially affect parsing or interpretation. Inadequately policing this
can lead to vulnerabilities in web applications, most notably HTTP
Response Splitting.
NIO was insufficiently policing the correctness of the header fields we
emit in HTTP/1.1. We've therefore added a new handler that is
automatically added to channel pipelines that will police the validity
of header fields.
For projects that are already running the validation themselves, this
can be easily disabled. Note that by default NIO does not validate
content length is correctly calculated, so applications can have their
framing fall out of sync unless they appropriately calculate this
themselves or use chunked transfer encoding.
Modifications
- Add thorough unit testing to confirm we will not emit invalid header
fields.
- Error if a user attempts to send an invalid header field.
Result
NIO applications are no longer vulnerable to response splitting by CRLF
injection by default.
* Adopt `Sendable` for closures in `HTTPPipelineSetup.swift`
* make `UnsafeTransfer` and `UnsafeMutableTransferBox` available in Swift 5.4 too
* fix code duplication
* Copy `UnsafeTransfer` to `NIOHTTP1Tests` to be able to remove `@testable` from `NIOCore` import
Motivation:
As we've largely completed our move to split out our core abstractions,
we now have an opportunity to clean up our dependencies and imports. We
should arrange for everything to only import NIO if it actually needs
it, and to correctly express dependencies on NIOCore and NIOEmbedded
where they exist.
We aren't yet splitting out tests that only test functionality in
NIOCore, that will follow in a separate patch.
Modifications:
- Fixed up imports
- Made sure our protocols only require NIOCore.
Result:
Better expression of dependencies.
Co-authored-by: George Barnett <gbarnett@apple.com>
Motivation:
We recently added a synchronous view of the `ChannelPipline` so that
callers can avoid allocating futures when they know they're on the right
event loop. We also offer convenience APIs to configure the pipeline for
particular use cases, like an HTTP/1 server but we don't have
synchronous versions of these APIs yet. We should have parity
between as synchronous and asyncronous APIs where feasible.
Modifications:
- Add synchronous helpers to configure HTTP1 client and server pipelines
Result:
Callers to synchronously configure HTTP1 client and server pipelines.
Motivation:
Networking software like SwiftNIO that always has explicit flushes
usually does not benefit from having TCP_NODELAY switched off. The
benefits of having it turned on are usually quite substantial and yet we
forced our users for the longest time to enable it manually.
Quite a bit of engineering time has been lost finding performance
problems and it turns out switching TCP_NODELAY on solves them
magically.
Netty has made the switch to TCP_NODELAY on by default, SwiftNIO should
follow.
Modifications:
Enable TCP_NODELAY by default.
Result:
If the user forgot to enable TCP_NODELAY, their software should now be
faster.
* Reorder ‘channel active’ calls to the same order as `_ChannelInboundHandler` and their likely chronological order.
Motivation:
When first viewing the example classes, coming to the ‘read’ method first, leaves the subject unclear as to what the method is ‘reading’.
It is preferable to view something being sent first, and then to view the reading of the response.
It also matches the call order against the protocol making it a little easier for those unfamiliar with the protocol to see which methods have been implemented.
Modifications:
Moved channel active calls to be top of the class.
Despite the diff there are no actual code modifications.
UDP Client changed to indent using spaces to match rest of project. Incidental change.
Result:
The examples are slighter clearer to read, particularly for newcomers to swift-no as the calls are in a logical chronological order.
* Fix an error in the upgrader and its tests which checked the connection header incorrectly.
Motivation:
To correct the logic in the upgrader. Previously it checked if the upgraders required headers include the connection header. Now it checks that the connection header value was present as a separate header in the incoming request.
To prepare the class naming for the presence of a client upgrader.
Modifications:
Slight change in server upgrader handler logic with accompanying tests.
Renamed upgrader and test files to include the word ‘server’.
Ran the linux test script.
Result:
The server upgrader now checks for the presence of the connection header value as a header of its own.
* Rename WebSocketServer upgrader to make the naming clearer and make way for a client version.
Motivation:
To make the web socket upgrader naming clearer, particularly once we add a client version.
Modifications:
Rename WebSocketUpgrader too WebSocketServerUpgrader.
Result:
Improved clarity of naming on the web socket upgrader.
* Adds correct naming conventions to NIOWebSocketServerUpgrader. Sets back an incorrect fix (non-fix).
* Move deprecation for NIOWebSocketServerUpgrader typealias out of API shims file.
* Makes HTTPEncoder removable.
Adds a client upgrade handler with tests.
Adds the ability to use a client upgrader to the client setup.
Initial linux file update.
* Allow assertContains to be accessed publicly, so that it can be used in the client side tests.
* Update tests to remove server upgrader from client tests.
Change client tests to use Embedded channel.
Update HTTPUpgradeConfiguration class name to be NIOHTTPServerUpgradeConfiguration
Few other small stylistic changes.
* Removed awaiting upgrader state.
Removed future from handle upgrade call as is synchronous.
Removed protocol iterator from handle upgrade call as is not required by the client.
* Ensure that the client handler calls for the HTTPPipeline are backwards compatible.
Ensure that incoming promises to the handler write call are completed.
Neaten the upgrade header formation to remove looping.
Improve the correctness of the upgrade error throwing.
* Update scripts to match new unit tests.
* Change the documentation for HTTPServerPipeline to remove nil options which have now been removed.
* Restore an incorrectly added server pipeline comment change and make it to the client pipeline instead.
* Raise the allocation limits in the docker images to allow the tests to pass.
Motivation:
The old HTTP parser tried to convert `http_parser` to a one-shot parser
by pausing it constantly. That was done to be resilient against
re-entrancy. But now, we have the new `ByteToMessageDecoder` which
protects against that so HTTP decoder can just become a real
`ByteToMessageDecoder`. It also serves as a great testbed for
`ByteToMessageDecoder`.
Modifications:
- make the HTTP decoder a `ByteToMessageDecoder`
- refactor the implementation
Result:
cleaner code, more use of `ByteToMessageDecoder`
Motivation:
- `ChannelPipeline.add(name:handler:...)` had a strange order of arguments
- `remove(handler:)` and `remove(ctx:)` both remove `ChannelHandler`s
but they read like they remove different things
So let's just fix the argument order and name them `addHandler` and
`removeHandler` making clear what they do.
Modifications:
- rename all `ChannelPipeline.add(name:handler:...)`s to `ChannelPipeline.addHandler(_:name:...)`
- rename all `ChannelPipeline.remove(...)`s to `ChannelPipeline.removeHandler(...)`
Result:
more readable and consistent code
Motivation:
public/internal modifiers for `extension`s are confusing as a
`func foo` is public if within a `public extension`.
Modifications:
remove all `internal` (redundant) and `public` (dangerous) modifiers for
`extensions`.
Result:
- code easier to read
- code much easier to review in a small diff
Motivation:
If ChannelHandler removal worked correctly, it was often either by
accident or by intricate knowledge about the implementation of the
ChannelHandler that is to be removed. Especially when it comes to
re-entrancy it mostly didn't work correctly.
Modifications:
- introduce a `RemovableChannelHandler` API
- raise allocation limit per HTTP connection by 1
(https://bugs.swift.org/browse/SR-9905)
Result:
Make things work by contruction rather than accident
Motivation:
For compatibility reasons, we used to disable HTTP1 error handling by
default to not break SemVer.
Modifications:
enable HTTP1 error handling by default
Result:
HTTP1 protocol errors now handled automatically by default
Motivation:
NIO2 development starts now.
Modifications:
Made NIO Swift 5-only for everything else see docs/public-api-changes-NIO1-to-NIO2.md
Result:
NIO2 development can start.
Motivation:
Swift 5 complains on redundant modifiers. For example declaring a
`public func` inside of a `public extension` is now a warning. I don't
agree with this but I dislike warnings even more, so...
Modifications:
remove all redundant modifiers that the compiler now warns about such as
swift-nio/Sources/NIOPriorityQueue/PriorityQueue.swift:90:5: warning: 'public' modifier is redundant for property declared in a public extension
Result:
no warnings in Swift 5
Motivation:
398b950eee introduced a change which forwarded bytes that were buffered in HTTPDecoder after it was removed when an upgrade was detected. This may be risky if we dont know that the pipeline can handle it.
Modifications:
- Add new initializer that allow us to configure if we should forward bytes or not.
- Automatically use this if we know that we added an upgrader
- Add unit tests.
Result:
Less risky implementation.
Motivation:
Currently the HTTP decoders can throw errors, but they will be ignored
and lead to a simple EOF. That's not ideal: in most cases we should make
a best-effort attempt to send a 4XX error code before we shut the client
down.
Modifications:
Provided a new ChannelHandler that generates 400 errors when the HTTP
decoder fails.
Added a flag to automatically add that handler to the channel pipeline.
Added the handler to the HTTP sample server.
Enabled integration test 12.
Result:
Easier error handling for HTTP servers.
Motivation:
The current HTTP server helpers are not modular, meaning that each
time we add a new first-party HTTP handler we need to add a brand new
method. Additionally, they do not currently compose, so if you want
assistance with HTTP pipelining *and* to support HTTP upgrade you are
out of luck.
Modifications:
Deprecate the two existing server helpers.
Add a new server helper that can be extended to support all of the
possible features that users may want in their HTTP pipelines.
Result:
Users will have a single place to go that can be used to configure
their HTTP server pipeline, and that understands how the different
handlers fit together in a complete pipeline.