Skip to content

2.0.0 — Streaming and HTTP hardening

Choose a tag to compare

@Maartz Maartz released this 04 Oct 18:24
· 11 commits to main since this release

Nexus 2.0 adds demand-driven response streaming and hardens HTTP behavior across Hummingbird and Vapor. This is a major release because streaming callbacks and parameter decoding have changed.

What's new

  • Vapor adapter: use Nexus pipelines as Vapor 4 middleware, alongside the existing Hummingbird adapter.
  • Lazy response producers: ResponseBody.producer and ResponseBodyWriter await transport writes. Chunked responses, files, and SSE finish when the producer returns and abort when it throws.
  • Connection helpers: request metadata, repeated-header access, header transformations, private framework data, and additional session persistence options.
  • Testing: expanded request builders, property generators, and real TCP tests for slow readers, disconnects, response aborts, and HEAD/bodyless responses on both adapters.

What's fixed

  • Valid gzip and zlib-wrapped deflate output, quality-aware negotiation, and cache/no-transform handling.
  • Repeated session middleware preserves in-request changes and avoids duplicate cookies.
  • Favicon HEAD and conditional requests, deterministic ETags, and timeout edge cases.
  • Vapor query strings, IPv6 authority, repeated headers/cookies, request body limits, and streaming failures.
  • HEAD/304 representation lengths and body suppression on both adapters.
  • SwiftCheck failures and exhausted generators now reach Swift Testing.
  • Linux CI preserves test failure exit codes. Coverage merges all test executables and enforces 85% coverage using unique executable source lines from LCOV.

Migrating from 1.x

Use from: "2.0.0" in your package dependency. Chunked and SSE writes now require try await:

conn.sseEvent { writer in
    try await writer.write(SSEEvent(data: "ready", event: "status"))
}

Remove finish() calls and nested producer Tasks. Throw to abort. Both sendChunked and sseEvent halt the pipeline; exhaustive ResponseBody switches must handle .producer. Existing .stream(AsyncThrowingStream) remains supported with caller-managed buffering and lifecycle.

Query/form duplicates now use the last value, and query + decodes to a space. Combined parameters prioritize path, then body, then query. Use queryParameters to retain all query values.

The package uses Swift tools 6.0. Linux builds need zlib development headers (apt-get install zlib1g-dev on Debian/Ubuntu).

Validation and limits

967 tests pass on macOS with Swift 6.4 and Linux arm64 with Swift 6.0.3. Two intentional known-issue probes test the property assertion bridge. Live transport checks cover HTTP/1; HTTP/2, TLS/proxy streaming, WebSocket behavioral parity, and load performance were not validated by this pilot.

GitHub coverage checks passed with 89.03% source line coverage on macOS and 88.92% on Linux, above the 85% gate.

Idle SSE producers should send heartbeat comments and propagate write failures. Immediate disconnect cancellation while awaiting unrelated work is not guaranteed.

Full changelog · Changes since 1.3.0