Commit Graph
228 Commits
Author SHA1 Message Date
Fabian Fett 6a6f7d7c33 Centralize UnsafeTransfer in NIOCore (#3492)
We have a number of copies of `UnsafeTransfer` and two copies of
`UnsafeMutableTransferBox` in our code base. Before introducing more of
those, lets centralize to just one using a `package` access modifier.
2026-02-03 10:27:30 +00:00
Adam FowlerandCory Benfield 61053a00bb NIOTypedHTTPClientUpgradeHandler will write Upgrade request on handlerAdded if active (#3473)
`NIOTypedHTTPClientUpgradeHandler.handlerAdded` will write upgrade
request if the channel is already active

### Motivation:

This has been added to make it easier to implement a websocket client
that supports proxies. If the upgrade handler is added after the proxy
connect has been processed previously nothing would happen.

### Modifications:

- Added new function
`NIOTypedHTTPClientUpgradeHandler.writeUpgradeRequest()` function. Call
this from `channelActive` and also from `handlerAdded` if the channel is
already active.
- Added test `testUpgradeHappensAfterHandlerAdded`

### Result:

NIOTypedHTTPClientUpgradeHandler now also works if it is added to a
channel after the channel is active

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2026-01-14 11:40:00 +00:00
Zamderax ec26755611 Tests: inline TestUtils.swift in NIOHTTP1Tests to avoid broken symlink on non-symlink filesystems (#3426)
On filesystems without symlink support for Windows, the symlinked test
helper at is materialized as a plain text file containing the relative
path, which breaks compilation with errors like:
```
expressions are not allowed at the top level
cannot find 'assertNoThrowWithValue' in scope
```
This change inlines the contents, restoring the intended shared test
utilities for the NIOHTTP1 test target. This helps Windows compile the
Test target
2025-10-29 13:27:40 +00:00
George BarnettandCory Benfield a65e9735ac Drop all server response parts after an invalid header (#3339)
Motivation:

NIOHTTPResponseHeadersValidator drops head/end response parts if they
contain invalid header fields. If a head part is dropped and the server
allows pipelining then the subsequent body/end part will reach the
pipelining handler and result in an assertion failure in debug builds.
In release builds, some parts may be incorrectly written out leading to
protocol violations.

Modifications:

- Drop all response parts after an invalid response part

Result:

- Fewer bugs
- Resolves #3326

Co-authored-by: Cory Benfield <lukasa@apple.com>
2025-08-12 09:33:24 +00:00
Max Desiatov 175417d85c Fix typo in HTTPServerClientTest.swift comments (#3323)
`we read faster then we can write` -> `we read faster than we can write`
2025-07-28 12:46:19 +00:00
Cory Benfield c9e2ac115f Adjust for SendableMetatype (#3266)
Motivation

With the introduction of isolated conformances, it has become necessary
to start managing the use of metatypes for some of our protocols. In
general, we don't want to force the relevant protocols to only be
conformed in non-isolated forms. Instead, we just want to make the
specific APIs non-usable.

Modifications

- Add shims for SendableMetatype that only use it when it is available.
- Require SendableMetatype where needed, gated by @preconcurrency.

Result

We continue to be safe.
2025-06-13 09:12:25 +01:00
Rick Newton-Rogers 57658e12ff Drop Swift 5.9 (#3228)
Motivation:

Swift 5.9 is no longer supported, we should bump the tools version and
remove it from our CI.

Modifications:

* Bump the Swift tools version to Swift 5.10
* Remove Swift 5.9 jobs where appropriate in main.yml, pull_request.yml

Result:

Code reflects our support window.
2025-05-07 12:24:44 +00:00
Cory BenfieldandGeorge Barnett 6e17bc9468 Update LLHTTP and apply patch to support C++ interop (#3216)
### Motivation

C++ interop support in Xcode has started to dislike the header files
from llhttp. While a bug has been filed upstream at
https://github.com/nodejs/llparse/issues/71 it doesn't seem as though
there is any movement on that fix upstream. As a result, we need to
apply a patch.

To keep the code maintainable, we'd like to apply that patch in an
automated fashion, so we should do so by amending the "update and patch"
script. Along the way, we should update LLHTTP to the latest code.

### Modifications

The modifications are split into separate commits.

1. Modify the script to fix some bugs that have crept in.
2. Run the script to update LLHTTP to latest, without the patch.
3. Fix up the tests to account for the fact that we get some different
errors from LLHTTP now.
4. Apply the patch suggested by @postmechanical in #3093
5. Re-run the script, which only applies the patch

### Result

C++ interop should be working again. Resolves #3093.

---------

Co-authored-by: George Barnett <gbarnett@apple.com>
2025-04-22 13:11:47 +01:00
Adam FowlerandCory Benfield d7a8ff6e36 Add errorCaught to NIOTypedHTTPClientUpgradeHandler (#3210)
To handle errors fired by previous ChannelHandlers. eg
NIOSSLClientHandler

### Motivation:

Otherwise if a ChannelHandler previous to the upgrade ChannelHandler
fails the error returned is `inappropriateOperationForState` and the
error fired by the original ChannelHandler is lost.

Added `testReturnsErrorsFromPriorChannelHandlers`. Also had to
reorganise `setUpClientChannel` slightly so I could get the result of
the upgrade.

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2025-04-16 14:24:42 +00:00
George BarnettandRick Newton-Rogers 202f987738 Strict concurrency for NIOHTTP1Tests (#3169)
Co-authored-by: Rick Newton-Rogers <rnro@apple.com>
2025-04-07 11:27:05 +01:00
Rick Newton-Rogers 5f60ceeca0 Enable strict concurrency checking for NIOHTTP1 (#3115)
### 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.
2025-02-19 15:04:51 +00:00
bf41ad1595 Improve HTTPHeaders description performance (#3063)
### Motivation:

As outlined in this
[issue](https://github.com/apple/swift-nio/issues/2930) by @weissi, the
current performance of calling `description` on `HTTPHeaders` is
undermined by the dynamism of Array.

### Modifications:

The proposed solution replaces the implementation of `description` to
iterate over the items and print them out manually. This provides a
faster solution since we bypass the cost of calling into `description`
of an Array.


### Result:

A more performant implementation of `HTTPHeaders` description.

---------

Co-authored-by: Johannes Weiss <johannesweiss@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
2025-01-20 16:39:21 +00:00
Cory Benfield 742ae54a2f Fix new warnings (#3026)
Motivation:

6.0.3 added new warnings about Sendable issues, so let's fix those to
keep things warnings free.

Modifications:

A bunch of Sendable usage fixes.

Result:

Warnings free builds again!
2024-12-13 16:52:38 +00:00
Johannes Weiss 6ba8f4f04a fix almost all Sendable warnings (#2994)
### Motivation:

Opening the `swift-nio` repository made me warning blind because there
were always so many trivially fixable warnings about things that were
correct but cannot be understood by the compiler.

### Modifications:

Fix all the sendable warnings that popped up, except for one test where
`NIOLockedValueBox<Thread?>` isn't sendable because `Foundation.Thread`
seemingly isn't `Sendable` which is odd. Guessing that'll be fixed on
their end.

### Result:

- Fewer warnings
- Less warning-blindness
- More checks
2024-11-25 17:56:44 +00:00
Johannes Weiss 0ee1657e8a Make NIOFileDescriptor/FileRegion/IOData Sendable & soft-deprecated (#2598)
Motivation:

`IOData` is a legacy but alas also core type that needs to be
`Sendable`. Before this PR however it can't be `Sendable` because it
holds a `FileRegion` which holds a `NIOFileDescriptor`. So let's make
all of these `Sendable` but let's also start the deprecation journey for
the following types:

- `IOData`, now soft-deprecated (no warnings) because on its reliance on
`FileRegion`
- `FileRegion`, now soft-deprecated (no warnings) because on its
reliance on `NIOFileHandle`
- `NIOFileHandle`, now soft-deprecated (warnings on the
`NIOFileHandle(descriptor:)` constructor but with a
`NIOFileHandle(_deprecatedTakingOwnershipOfDescriptor:)` alternative
- `NonBlockingFileIO`, now soft-deprecated (warnings on the `openFile`
functions (but with `_deprecated` alternatives) because of their
reliance on `NIOFileHandle)

Modification:

- Make `NIOFileDescriptor`, `FileRegion` and `IOData` `Sendable` by
tracking the fd number and the usage state in an atomic
- Enforce singular access by making the `withFileDescriptor { fd ... }`
function atomically exchange the fd number for a "I'm busy" sentinel
value
- Start deprecating `IOData`, `NIOFileHandle`, `NonBlockingFileIO`,
`FileRegion`

Result:
- `NIOFileDescriptor`, `FileRegion` and `IOData` can be `Sendable`
2024-11-25 16:05:30 +00:00
Adam FowlerandFranz Busch a026de35e0 Close channel during upgrade, if client closes input (#2756)
Check for half closure during server upgrade and close channel if client
closes the channel

### Motivation:

This is to fix #2742 

### Modifications:

Add `userInboundEventTriggered` function to
`NIOTypedHTTPServerProtocolUpgrader` which checks for
`ChannelEvent.inputClosed`

### Result:

Negotiation future now errors when client closes the connection instead
of never completing

---------

Co-authored-by: Franz Busch <privat@franz-busch.de>
2024-11-14 18:15:12 +00:00
Cory Benfield de116b7eff Clean up Sendability for ChannelInvoker (#2955)
Motivation:

The ChannelInvoker protocols are an awkward beast. They aren't really
something that people can do generic programming against. Instead, they
were designed to do API sharing. Of course, they didn't do that very
well, and the strict concurrency checking world has revealed this.

Much of the API surface on ChannelInvoker is confused. There are
NIOAnys, which aren't Sendable. We allow sending user events without
requiring Sendable. And our two main conforming types are
ChannelPipeline and ChannelHandlerContext, two types with wildly
differing thread-safety semantics.

This PR aims to clean that up.

Modifications:

- Deprecated all API surface on ChannelInvoker protocols that uses
NIOAny.

    ChannelInvoker has to be assumed to be a cross-thread protocol,
    and that requires that it only use Sendable types. NIOAny isn't,
    so these methods are no longer sound.

- Re-add non-deprecated versions on ChannelHandlerContext.

    While it's not safe to use the NIOAny methods on Channel or
    ChannelPipeline, it's totally safe to use them on
    ChannelHandlerContext. So we keep those available and
    undeprecated.

- Provide typed generic replacements on ChannelPipeline and on Channel

    To replace the NIOAny methods on ChannelPipeline and Channel
    we can use some typed generic ones instead. These are not
    defined on ChannelInvoker, as the methods are useless on
    ChannelHandlerContext. This begins the acknowledgement that
    ChannelHandlerContext should not have conformed to these
    protocols at all.

- Add Sendable constraints to the user event witnesses on ChannelInvoker

    Again, these were missing, but must be there for Channel and
    ChannelPipeline.

- Provide non-Sendable overloads on ChannelHandlerContext

    ChannelHandlerContext is thread-bound, and so may safely pass
    non-Sendable user events.

Result:

One step closer to strict concurrency cleanliness for NIOCore.
2024-10-31 11:30:27 +00:00
Cory Benfield 411c2c553c Handle Sendability of RemovableChannelHandler (#2953)
Motivation:

RemovableChannelHandlers have a large API surface in NIOCore. That API
surface is a bit awkward with regard to strict concurrency, and needs
some cleanup.

Modifications:

This patch adds some new API that is necessary to safely work with
RemovableChannelHandlers, deprecates some API that cannot plausibly be
used, and cleans up some other parts of the API.

Result:

Easier to work with RemovableChannelHandlers
2024-10-29 10:40:47 +00:00
Ayush Garg 7840b6b067 ChannelOption: Allow types to be accessed with leading dot syntax (#2816)
Motivation:

Since Swift 5.5 and [SE-0299](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0299-extend-generic-static-member-lookup.md) it is possible to add static members to protocols which are discoverable through the shorthand dot syntax.
This change reduces type repetition and improves call-site legibility.

Modifications:

Added extensions for ChannelOption with static members where Self is bound to a concrete type.

Result:

ChannelOption types can be used with the leading dot syntax. For eg:

```
//before
.channelOption(ChannelOptions.explicitCongestionNotification, value: true)
.channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)

//after
.channelOption(.explicitCongestionNotification, value: true)
.channelOption(.socketOption(.so_reuseaddr), value: 1)
```
2024-07-30 15:19:59 +00:00
Franz Busch c9756e1083 Adopt swift-format (#2794)
* 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.
2024-07-19 11:48:17 +02:00
Johannes Weiss 7948ed2104 ChannelHandler: provide static (un)wrap(In|Out)bound(In|Out) (#2791) 2024-07-18 11:55:48 +01:00
Dimitri Bouniol 72cab7d9a4 Correctly mark 304 as not having a response body (#2737)
* Fixed an issue where HTTP/2 connections would disconnect if response compression were used and a 304 Not Modified response was returned

* Added HTTP encoder tests for 304 Not Modified responses
2024-06-12 18:30:58 +01:00
Franz BuschandCory Benfield 63e8c4e1aa Migrate to syncOperations in more places (#2661)
# Motivation

Adding a handler via the regular `pipeline.addHandler` APIs can lead to transferring the handler over isolation regions. To avoid running into `Sendable` warnings here we can use the `syncOperations` of the pipeline to avoid transferring the handlers.

# Modification

This PR is mostly changing code to avoid transferring handlers to and from the event loops in tests. This should be a no-op mostly.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2024-03-01 15:05:22 +00:00
hamzahrmalik a60f1972d1 Add tests to validate the behaviour when requests/response content-length headers are wrong in HTTP1 (#2601)
Add tests to validate the behaviour when requests/response content-length headers are wrong
2023-11-30 01:23:25 -08:00
Franz Busch 702cd7c56d Fix the typed HTTP upgrade compiler guards (#2594)
The compiler guards were unnecessarily complex and I also didn't cover 3 methods where we used the types.
2023-11-16 03:30:21 -08:00
Franz Busch c46199386c Revert "Back out new typed HTTP protocol upgrader (#2579)" (#2593)
* Revert "Back out new typed HTTP protocol upgrader (#2579)"

# Motivation
We have reverted the typed HTTP protocol upgrader pieces since adopters were running into a compiler bug (https://github.com/apple/swift/pull/69459) that caused the compiler to emit strong references to `swift_getExtendedExistentialTypeMetadata`. The problem is that `swift_getExtendedExistentialTypeMetadata` is not available on older runtimes before constrained existentials have been introduced. This caused adopters to run into runtime crashes when loading any library compiled with this NIO code.

# Modifications
This PR reverts the revert and guard all new code in a compiler guard that checks that we are either on non-Darwin platforms or on a new enough Swift compiler that contains the fix.

# Result
We can offer the typed HTTP upgrade code to our adopters again.

* Add compiler guards
2023-11-15 18:58:27 +00:00
Franz Busch 8c238f2cc1 Back out new typed HTTP protocol upgrader (#2579)
# Motivation
We got reports in https://github.com/apple/swift-nio/issues/2574 that our new typed HTTP upgrader are hitting a Swift compiler bug which manifests in a runtime crash on older iOS/macOS/etc.

# Modification
This PR backs out the new typed HTTP protocol upgrader APIs so that we can unblock our users until the Swift compiler bug is fixed.

# Result
No more crashes for our users.
2023-10-27 15:48:23 +01:00
hamzahrmalik b7c122e09e Fix flakiness in testDelayedUpgradeBehaviour (#2557) 2023-10-18 07:54:51 -07:00
hamzahrmalikandCory Benfield a41b02c580 Avoid terminating when a precondition is not met in HTTPServerPipelineHandler (#2550)
* Avoid terminating when a precondition is not met in HTTPServerPipelineHandler

* Address review comments

* rename precondition to assertion

---------

Co-authored-by: Cory Benfield <lukasa@apple.com>
2023-10-18 06:26:43 -07:00
Rick Newton-RogersandFranz Busch a9071cc110 waitForUpgraderToBeRemoved availability guard (#2559)
Motivation:

Tests fail to compile on 5.7, 5.8

Modifications:

Add waitForUpgraderToBeRemoved availability guard

Result:

Tests should compile

Co-authored-by: Franz Busch <f.busch@apple.com>
2023-10-17 09:10:53 -07:00
Franz Busch f38b7fd38a Remove SPI from NIOAsyncChannel, new bootstrap methods, protocol negotiation and HTTP upgrade. (#2548)
# Motivation
Over the past months, we have been working on new async bridges to make using NIO's `Channel` from Swift Concurrency possible. Since this work was far reaching we have opted to land all of it as SPI. Now the time has come and we feel confident enough to make the SPI official API. This comes after testing the new APIs in various scenarios such as HTTP 1&2, HTTP upgrades, protocol negotiation and in benchmarks.

# Modification
This PR removes the SPI from the `NIOAsyncChannel`, the bootstrap methods, protocol negotiation and HTTP upgrade.

# Result
Everyone can use the our new APIs🚀
2023-10-17 14:14:02 +01:00
Franz Busch e9676f9271 Fix flaky testRemovesAllHTTPRelatedHandlersAfterUpgrade test (#2552)
# Motivation
This test has been flaky since we only waited for the untyped handler to be removed but we also execute this test for the typed test subclass.

# Modification
This PR fixes the test by also waiting for the typed handler to no longer be present in the pipeline.

# Result
Less flaky tests.
2023-10-16 10:40:46 +01:00
Franz Busch 4ab8b98f9d Introduce new typed HTTPClientUpgrader and WebSocketClientUpgrader (#2526)
* Introduce new typed `HTTPClientUpgrader` and `WebSocketClientUpgrader`

# Motivation
In my previous PR https://github.com/apple/swift-nio/pull/2517, I added a new typed `HTTPServerUpgrader` and corresponding implementation for the `WebSocketServerUpgrader`. The goal of those is to carry type information across HTTP upgrades which allows us to build fully typed pipelines.

# Modification
This PR adds a few things:
1. A new `NIOTypedHttpClientUpgradeHandler` + `NIOTypedHttpClientProtocolUpgrader`. I also moved the state handling to a separate state machine. Similar to the server PR I did not unify the state machine between the newly typed and untyped upgrade handlers since they differ in logic.
2. A new `NIOTypedWebSocketClientUpgrader`
3. An overhauled WebSocket client example.

# Result
This is the last missing piece of dynamic pipeline changing where we did not carry around the type information. After this PR lands, we can finalize the `AsyncChannel` and async typed NIO pieces.

* Remove availability on the protocols
2023-10-06 16:33:25 +01:00
Franz Busch ded781e2dd Fix test availability for tests (#2533)
# Motivation

Building on Darwin is currently broken since we are missing availability annotations on some of the tests.
2023-10-05 07:03:00 -07:00
David Nadoba d367dc0a87 Tolerate empty HTTP response body parts (#2531)
* Tolerate empty HTTP response body parts

### Motivation

Empty HTTP response body parts currently eagerly end a response. This is unexpected and against NIOs documented behaviour.

### Modification

- add test which send an empty response body part and would previously fail
- skip empty response body parts

### Result

Users can send empty body parts without ending the response.

* add comment explaining why we do it here instead of fixing it at the source

* move empty body part logic to `writeChunk`
2023-10-04 06:42:26 -07:00
Franz Busch de07e573d6 Introduce new typed HTTPServerUpgrader and WebSocketServerUpgrader (#2517)
* Introduce new typed `HTTPServerUpgrader` and `WebSocketServerUpgrader`

# Motivation
With our new `NIOAsyncChannel` and typed bootstrap APIs we want to be able to let users spell out their pipeline in a typed way. Pipelines can contain handlers that have to make a forking decision such as HTTP upgrading. Our current `HTTPServerUpgradeHandler` is one of those handlers but it lacks strict typing. To interact nicely with our new typed APIs we need to have a new variant of the `HTTPServerUpgradeHandler` that can carry type information.

# Modification
This PR adds a few things:
1. A new `NIOTypedHTTPServerUpgradeHandler` + `NIOTypedHTTPServeProtocolUpgrader`. I also moved the state handling logic to a separate state machine. I thought about unifying the state machines of the _old_ handler and the new one but they differ in behaviour which makes the state machine more complicated.
2. A new `NIOTypedWebSocketServerUpgrader` that conforms to `NIOTypedHTTPServerProtocolUpgrader`
3. An overhauled WebSocket server example that fully uses Concurrency.

# Result
We now have a way to fully type the server side of HTTP protocol upgrading.

Code review

Update parameter names for new API and fix example

* Introduce new configuration struct and rename to `UpgradablePipeline`

* Review comments
2023-10-02 07:26:16 -07:00
Rick Newton-Rogers 67553a7d6d Bump minimum Swift version to 5.7 (#2524)
* 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
2023-10-02 11:38:07 +01:00
Cory Benfield 7d9f892d83 Support users opting-out of us setting framing headers. (#2508)
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.
2023-08-22 02:51:05 -07:00
Cory Benfield 2d8e6ca36f Tolerate sending data after close(mode: .output) (#2421)
Motivation

We shouldn't crash on somewhat likely user error.

Modifications

Pass on writes after close(mode: .output) instead of crashing.

Result

User code is more robust to weird edge cases.
2023-05-09 10:52:48 +01:00
Cory Benfield 5f8b0647e4 Handle close(output) in the pipeline handler. (#2414)
Motivation:

Currently the server pipeline handler ignores close. This generally works,
except in the rare case that the user calls close(mode: .output). In this
instance they have signalled that they'll never write again, and they're
likely expecting a final close shortly after.

However, it is possible that the pipeline handler has suspended reads
at the same time. On Linux this isn't an issue, because we'll still be told
about the eventual socket close. However, on Apple platforms we won't: we've
masked off the reads, and we can't listen to EVFILT_EXCEPT due to some
other issues. This means that on Apple platforms the server pipeline handler
can accidentally wedge the Channel open and prevent it from closing.

We should take this opportunity to have the server pipeline handler be smart
about close(mode: .output). What _should_ happen here is that the pipeline
handler should immediately refuse to deliver further requests on the Channel.
If one is in-flight, it can continue, but everything else should be dropped.
This is because the server cannot possibly respond to further requests.

Modifications:

- Add new states to the server pipeline handler
- Drop buffered requests and new data after close(mode: .output)
- Add tests

Result:

Server pipeline handler behaves way better.
2023-04-28 06:22:07 -07:00
David Nadoba 6720612111 Drop Swift 5.5 (#2406)
* Drop Swift 5.5

* Use `swift-atomics` 1.1.0 with `Sendable` adoption
2023-04-17 08:40:35 +01:00
carolinacass af41276062 Use #fileID/#filePath instead of #file (#2306)
Motivation:

#fileID introduced in Swift 5.3, so no longer need to use #file anywhere

Modifications:

Changed #file to #filePath or #fileID depending on the situation
2022-11-03 16:43:13 +00:00
George Barnett 73eb597aa3 Don't unconditionally remove the HTTPServerUpgradeHandler (#2303)
Motivation:

The `HTTPServerUpgradeHandler` removes itself from the pipeline after an
upgrade and unbuffers any unconsumed reads. If an upgrade starts but
does not complete successfully then the pipeline may be left in an
unknown state.

If, for example, the failure occurs before the user provided upgrade
handler is run then unbuffered writes may be unwrapped by the wrong
channel handler as the wrong type leading to a crash.

Modifications:

- Only remove the upgrade handler and forward buffered writes if all
  parts of the upgrade complete successfully.
- If part of the upgrade fails then fire an error into the channel
  pipeline without removing the server upgrade handler.
- Remove a few unnecessary `map`s.
- Make `httpEncoder` non-optional since and remove associated dead code
  since it can never be `nil`.

Result:

Upgrade handling is safer.
2022-10-28 07:32:43 -07:00
David Nadoba c7b4989b02 Remove #if compiler(>=5.5) (#2292)
### Motivation
We only support Swift 5.5.2+.

### Modification
Remove all `#if swift(>=5.5)` conditional compilation blocks.

### Result
less branching
2022-10-13 07:17:46 -07:00
Cory Benfield 5aa44987f8 Correctly manage Content-Length on HEAD responses (#2277)
Motivation

When we receive a HEAD response, it's possible that the response
contains a content-length. llhttp has a bug
(https://github.com/nodejs/llhttp/issues/202) that prevents it from
properly managing that issue, which causes us to incorrectly parse
responses.

Modifications

Forcibly set llhttp's content-length value to 0.

Result

Correctly handle HTTP framing around llhttp's issues.
2022-10-04 06:59:57 -07:00
Cory Benfield a16e2f54a2 Merge pull request from GHSA-7fj7-39wj-c64f
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.
2022-09-27 13:09:52 +01:00
Cory Benfield 3cfd8ac5d9 Add support for newer LLHTTP status codes (#2269)
Motivation:

We should better tolerate LLHTTP status codes we don't yet know about.

Modifications:

- Added support for the status codes that currently exist
- Add a fallback to the RAW case for the future.

Result:

Better management of LLHTTP status codes
2022-09-16 08:33:40 -07:00
Cory Benfield 6918034260 Update HTTP parser to LLHTTP (#2263)
Motivation:

The node.js HTTP parser library that we use has been unmaintained for some time. We should move to the maintained replacement, which is llhttp. This patch will update our dependency and bring us over to the new library, as well as make any changes we need.

Modifications:

This patch comes in 4 parts, each contained in a separate commit in the PR.

The first commit drops the existing http_parser code and updates some of the repo state for using llhttp.
The second commit rewrites the update script to bring in llhttp instead of http_parser.
The third runs the actual script. You can skip reviewing this except to sanity check the outcome.
The fourth commit updates the NIO code and the tests to get everything working.

In general the substance of the product modifications was minimal. The logic around keeping track of where we are in the buffer and how upgrades work has changed a bit, so that required some fiddling. I also had to add an error reporting path for the delegates to be able to throw specific errors that llhttp no longer checks for. Finally, I removed two tests that were a little overzealous and that llhttp does not police.

Result:

Back on the supported path.
2022-09-13 14:09:57 +01:00
028cf7e606 HTTPResponseStatus should print code and reason (#2257)
* HTTPResponseStatus should print code and reason

* Update HTTPResponseStatusTests+XCTest.swift

Co-authored-by: Carolina Cassedy <ccassedy@apple.com>
Co-authored-by: Cory Benfield <lukasa@apple.com>
2022-08-31 05:37:08 -07:00
David Nadoba b99da5d3fe Workaround Sendable warning from Swift 5.7 (#2225)
Workaround for https://github.com/apple/swift/issues/59911
```swift
/src/Tests/NIOHTTP1Tests/HTTPTest.swift:148:21: warning: 'buf' mutated after capture by sendable closure
                buf.writeString("\(c)")
```
The variable `buf` is mutated but only before being capture by the sendable closure.

All other warnings/errors are fixed with the latest Swift 5.7 toolchain
2022-07-21 18:20:49 +01:00