Repository navigation
Releases: roost-framework/Nexus
Release list
2.1.0 — Optional Vapor adapter
Nexus 2.1 lets packages that only use the Hummingbird adapter skip Vapor entirely.
What's new
-
Vaporpackage trait:NexusVaporand its Vapor dependency now sit behind theVaportrait, which is on by default, so existing users are unaffected. Depend on Nexus withtraits: []and SwiftPM no longer fetches Vapor, routing-kit, multipart-kit, console-kit, or websocket-kit (about 75 MB of sources):.package(url: "https://github.com/roost-framework/Nexus.git", from: "2.1.0", traits: []),
What's fixed
HTTPRequest.arbitraryno longer generates an authority made only of whitespace or control characters. HTTPTypes stores such an authority as empty, so the generator broke its non-empty guarantee for some seeds.
Requirements
- Swift 6.1 or later (swift-tools-version 6.1), the first version with package traits. Swift 6.0 projects keep resolving Nexus 2.0.x.
See the changelog for details.
2.0.0 — Streaming and HTTP hardening
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.producerandResponseBodyWriterawait 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-transformhandling. - 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.
1.3.0 — NamedPipeline
What's New
Added
- NamedPipeline (Spec 29) — reusable, named middleware pipeline that can be declared once and applied to multiple routes or scopes. Conforms to
SendableandModulePlug, works with@PlugPipelineresult builder, and integrates via newscope(_:through:)overload acceptingNamedPipeline. Supports conditionals, loops, halt propagation, and nested scope composition.
let apiPipeline = NamedPipeline {
requestId()
auth
}
let router = Router {
scope("/api", through: apiPipeline) {
GET("/users") { conn in ... }
}
}CI
- Upgraded to Swift 6.3 toolchain across all CI jobs.
Full Changelog: 1.2.0...1.3.0
1.2.0 — Plug Feature Parity
Closes the critical gaps between Nexus and Elixir's Plug framework. Adds 10 new source files, 9 test suites (98 tests), bringing the total to 581 tests across 68 suites.
Highlights
- ModulePlug protocol — lightweight alternative to
ConfigurablePlugfor plugs with plain init parameters - Header helpers —
putRespHeader,getRespHeader,putReqHeader, etc. onConnection - Nested assigns — dot-path notation for hierarchical data:
conn.assign(dotPath: "user.role", value: "admin") - onError plug — centralized error handling that catches downstream errors
- Fetch session — explicit session loading control with
fetchSession,fetchSessionIfMissing - Route params access —
pathParameters,queryParameters, typedgetParameter(_:as:) - ContentNegotiation — validates
Acceptheaders, returns 406 on mismatch - Timeout — wraps plug execution with configurable duration, 503 on timeout
- PlugBuilder — declarative plug composition via Swift
@resultBuilder - Test helpers —
Connection.make(),.makeJSON(),.makeForm()factory methods
Fixes
- Linux CI: compression gracefully no-ops on platforms without Apple's
Compressionframework - Fixed sendFile race condition
Full changelog
https://github.com/Spectro-ORM/Nexus/blob/main/CHANGELOG.md
Full diff: 1.1.1...1.2.0
1.1.0 — Security, Telemetry & HTTP Compliance
What's New
Nexus 1.1.0 ships 10 new features across security, observability, HTTP compliance, and developer experience — with 76 new tests (448 total).
Security & Cryptography
- Message Encryption — AES-256-GCM encrypt-then-sign with HKDF-derived keys. The
MessageEncryption.encrypt/decryptAPI produces compact base64url tokens (<nonce>.<ciphertext+tag>.<hmac>). This is the foundation for encrypted cookie sessions. - Key Generator — PBKDF2-HMAC-SHA256 key derivation for turning human passwords into cryptographic keys. Pure HMAC implementation works identically on Apple and Linux. Verified against RFC 7914 test vectors.
HTTP Compliance
- Head Plug — Converts HEAD requests to GET before routing, then strips the response body via
registerBeforeSend. Per RFC 9110 §9.3.2, headers likeContent-LengthandContent-Typeare preserved. No more duplicate HEAD handlers or 404s. - Method Override — HTML forms only support GET and POST. The
methodOverride()plug rewrites POST requests to PUT, PATCH, or DELETE when a_methodform parameter (or query parameter) is present. Case-insensitive, security-constrained (only POST can be overridden, only to PUT/PATCH/DELETE). - Inform (103 Early Hints) — Queue informational 1xx responses with
conn.inform(status:headers:). Multiple calls queue in order. Non-1xx statuses are silently rejected. Stored in assigns for adapter extraction.
Observability & Debugging
- Telemetry — Emits
<prefix>.request.duration(Timer) and<prefix>.request.count(Counter) via swift-metrics withmethodandstatusdimensions. Wraps the pipeline to capture errors too — thrownNexusHTTPErroruses its status code, other errors use 500. - Debugger — Catches pipeline errors and renders a detailed HTML (or plain text) debug page showing the error type, message, request method/path/headers, query parameters, and connection assigns. Values for keys matching "secret", "password", "token", or "key" are automatically
[REDACTED]. Development only. - RewriteOn — Rewrites
conn.request.scheme,conn.request.authority, and remote IP fromX-Forwarded-Proto,X-Forwarded-Host, andX-Forwarded-Forheaders. Selective opt-in viarewriteOn([.forwardedProto, .forwardedFor]). Essential for apps behind reverse proxies.
Developer Experience
- Test Connection Recycling —
TestConnection.recycle(previousConn, path: "/next")parsesSet-Cookieresponse headers and injects them as aCookierequest header on a fresh connection. Cookies withMax-Age=0are excluded. Explicit cookies merge with/override recycled ones. - Content Negotiation Fix —
prefersHTMLnow defaults totruewhen theAcceptheader is missing, matching browser-default behavior forrespondTo.
Dependencies
- Added
swift-metrics(>= 2.0.0) to theNexuscore target for the telemetry plug. This is an API-only dependency — no metrics backend is bundled. - Added
NexusTestas a dependency ofNexusTestsfor test recycling tests.
API Notes
telemetry() and debugger() are wrapper functions (like rescueErrors) rather than pipeline plugs, because they need to observe the full pipeline lifecycle including thrown errors:
let app = telemetry(debugger(pipeline([
head(),
rewriteOn([.forwardedProto, .forwardedFor]),
requestId(),
bodyParser(),
methodOverride(),
sessionPlug(SessionConfig(secret: key)),
csrfProtection(),
router.callAsFunction,
])))Full Changelog
New files: Plugs/Head.swift, Plugs/MethodOverride.swift, Plugs/RewriteOn.swift, Plugs/Telemetry.swift, Plugs/Debugger.swift, MessageEncryption.swift, KeyGenerator.swift, Connection+Inform.swift, NexusTest/TestConnection+Recycle.swift
Modified: Package.swift (swift-metrics dep), Connection+Accept.swift (prefersHTML fix)
Test suites added: HeadTests (8), RewriteOnTests (10), DebuggerTests (12), TelemetryTests (7), MessageEncryptionTests (11), KeyGeneratorTests (9), InformTests (10), MethodOverrideTests (13), PrefersHTMLTests (14), TestRecycleTests (9)
v1.0.0 — Stable Release
Nexus reaches 1.0. The API is stable.
What's in the box
Core — Connection value type, Plug function typealias, pipe/pipeline composition, halt-not-throw error contract.
Router — Result-builder DSL with GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS/ANY, path parameters, wildcards, scoped routes with middleware, sub-router forwarding.
Content Types — JSON encode/decode, URL-encoded forms, multipart/form-data with file uploads, plaintext, HTML (with layout), XML, raw binary. Unified bodyParser() plug auto-detects Content-Type.
WebSocket — WSMessage, WSConnection, WS() route builder, Hummingbird adapter with .nexusWebSocket(). HTTP pipeline assigns propagate into WebSocket context.
Security — Signed cookie sessions (HMAC-SHA256), CSRF token protection, Basic auth, SSL redirect, CORS.
Typed Assigns — AssignKey protocol for compile-time-safe conn[KeyType.self] access. Built-in keys for request ID, session, remote IP, body params, uploaded files, parsed JSON.
Infrastructure — Static file serving, chunked streaming, SSE, file serving with MIME detection, request logging, request IDs, lifecycle hooks, configurable plugs, service injection.
Testing — NexusTest target with TestConnection builders. 354 tests. Swift 6 strict concurrency throughout. macOS + Linux CI.
Adapters — NexusHummingbird bridges to Hummingbird 2's HTTPResponder. Server-agnostic core.
Install
.package(url: "https://github.com/Spectro-ORM/Nexus.git", from: "1.0.0")