Change Log
August 16, 2026 ยท View on GitHub
Current Version
v7.1.1
v7.1.1
- Refreshed shipping dependencies with no public API changes:
IpMatcher1.0.5 -> 1.0.6,System.Text.Json10.0.5 -> 10.0.11, andSystem.Diagnostics.DiagnosticSource8.0.1 -> 10.0.11, picking up upstream security and reliability servicing - Hardened access-control IP matching so unsupported or cross-address-family matcher failures are treated as no match, preserving default-permit/default-deny behavior instead of aborting the request
- Refreshed
Watson.Clientsdependencies (net462/net48 targets):Microsoft.Bcl.AsyncInterfaces10.0.0 -> 10.0.11 andSystem.Buffers4.6.0 -> 4.6.1 - Updated test/tooling dependencies (RestWrapper, Inputty, Newtonsoft.Json, Microsoft.Playwright, Microsoft.NET.Test.Sdk, NUnit + adapter, xUnit visual-studio runner) to current releases and adapted
Test.Routingto RestWrapper'sSendAsyncAPI - Added negative and edge API-route coverage in
Test.Shared: malformed JSON body returns HTTP 400, unhandled handler exception returns HTTP 500InternalError, empty typed body deserializes to a null model, and unknown JSON fields are ignored
Unreleased
- Added
Watson.Clients, a companion package in this repository for outbound websocket client usage - Added
WatsonWebSocketClient,WebSocketClientSettings,WebSocketClientStatistics, and client-sideWebSocketMessagewith whole-message receive semantics and a rawClientWebSocketescape hatch - Added exhaustive shared websocket-client coverage in
Test.Shared, wired into bothTest.XUnitandTest.Automated, and extended server/client interop validation through that suite - Updated
Test.WebsocketClientto exerciseWatsonWebSocketClientinstead of rawClientWebSocket - Expanded
README.mdandMIGRATING_FROM_WATSONWEBSOCKET.mdso WatsonWebsocket client migrations now have first-class documentation alongside the server guidance
v7.1.0
- Added standardized, OpenTelemetry-shaped telemetry emitted through a
WatsonMeterandActivitySource; a host (Radiant, the OpenTelemetry SDK, Prometheus, or any listener) subscribes by name with no dependency taken by Watson on any collector - Added the four OpenTelemetry HTTP server metrics (
http.server.request.duration,http.server.active_requests,http.server.request.body.size,http.server.response.body.size) with label sets matching the OpenTelemetry HTTP semantic conventions - Added
watson.*metrics for connections, routing (match/unmatched by route type and template), authentication outcomes, aborts/disconnects, server exceptions, received/sent bytes, uptime/up, active HTTP/2 and HTTP/3 streams, and WebSocket sessions/handshakes - Added a per-request
Serverspan with W3C context propagation (traceparent/tracestate), bidirectional body-size and content-type attributes, and exception events - Added forwarded-header (
X-Forwarded-For/X-Forwarded-Proto) client-address resolution for spans, gated bySettings.Telemetry.TrustForwardedHeadersand a trusted-proxy allow-list; the raw socket peer is always recorded separately asnetwork.peer.address - Added an optional in-process Prometheus scrape endpoint served on the existing Watson listener at a configurable path (
Settings.Telemetry.Prometheus), so it opens no additional port and cannot create a listener port conflict; disabled by default - Added
WebserverSettings.Telemetry(TelemetrySettings) andWebserverBase.Telemetry(WebserverTelemetry); metrics that mirror the existing events and statistics surface are wired to it without touching the transport hot paths - Added shared telemetry coverage (
SharedTelemetryTests) exercised throughMeterListener/ActivityListener, wired into bothTest.AutomatedandTest.XUnit - Added a
System.Diagnostics.DiagnosticSource(8.0.1) package reference for thenetstandard2.1target, whereMeter/ActivitySourceare not in-box
v7.0.15
- Fixed active in-flight caller disconnect propagation so HTTP/1.1 socket disconnects, HTTP/2
RST_STREAMframes, and HTTP/3 response-side stream closures cancel the active request token and raiseRequestAborted/RequestorDisconnectedwhile route handlers are still running - Added shared protocol regression coverage for HTTP/1.1 caller disconnects and HTTP/2
RST_STREAMcancellation, wired into bothTest.AutomatedandTest.XUnit
v7.0.14
- Fixed HTTP/1.1 disconnect detection so transport aborts on response writes mark the active request aborted, cancel the per-request token, raise
RequestAborted, and raise the existingRequestorDisconnectedevent - Implemented the previously-declared
RequestorDisconnectedevent plumbing so disconnect observability now works end-to-end instead of remaining dead API surface - Corrected response observability so failed HTTP/1.1 sends no longer emit a false
ResponseSentsignal, and chunked/SSE finalization no longer marks failed final writes as successful - Prevented disconnect-triggered response send failures from falling through to the default "route did not send a response" HTTP 500 path
- Added deterministic shared-core coverage for disconnect transport-failure classification, request termination state, and failed final chunk/SSE sends
- Added end-to-end shared smoke coverage for successful chunked/SSE observability and for a client disconnect during a large HTTP/1.1 response, wired into both
Test.XUnitandTest.Automated
v7.0.13
- Fixed issue
#192, a shutdown race where disposing the server during active connection teardown could trigger an unobserved taskNullReferenceExceptionwhile releasing_RequestSemaphore - Captured the request semaphore per connection so shutdown can safely dispose and null the shared field without breaking in-flight
finallyblocks - Added regression coverage for disposing the server while idle TCP connections are still unwinding
v7.0.12
- Added OpenAPI schema composition support:
OpenApiSchemaMetadata.OneOf,OpenApiSchemaMetadata.Discriminator,OpenApiSchemaMetadata.CreateOneOf(...), andOpenApiSchemaMetadata.WithDiscriminator(...) - Added
OpenApiDiscriminatorMetadatamodelingpropertyNameand an optionalmapping - Added
OpenApiSettings.Schemasfor registering reusable component schemas emitted undercomponents.schemas - Updated
OpenApiDocumentGeneratorto emitoneOf,discriminator, andcomponents.schemas; the$refshort-circuit inBuildSchemais preserved for OpenAPI 3.0 compatibility - Added shared
Test.Shared.SharedOpenApiCompositionTestscovering metadata helpers, component schema registration,oneOfwith$refbranches, discriminator with and without mapping, scalar field regression, and$refshort-circuit; wired intoTest.AutomatedandTest.XUnit
v7.0.11
- Suppressed CA1416 platform compatibility warnings on QUIC call sites that are already guarded by runtime detection
- Fixed test ordering so the HTTP observability test no longer runs in the middle of the WebSocket test group
v7.0.10
- Added
netstandard2.1target for broader runtime compatibility (e.g. Unity, Xamarin, older .NET Core 3.x hosts) - HTTP/3 and QUIC features require .NET 8 or later; on
netstandard2.1they are gracefully unavailable - Added conditional polyfills for
Stream.ReadExactlyAsync,SHA1.HashData,FrozenDictionary,Task.WaitAsync,IThreadPoolWorkItem, andSslProtocols.Tls13on older target frameworks - Added
System.Text.JsonandMicrosoft.CSharppackage references for thenetstandard2.1target - Added cross-protocol route method parity test suite covering GET, POST, PUT, DELETE, PATCH, HEAD, and OPTIONS across HTTP/1.1, HTTP/2, and HTTP/3 for static routes, parameter routes, dynamic (regex) routes, content routes, and API routes
- Added
netstandard2.1compatibility unit tests validating runtime detection, protocol normalization, SHA1 handshake fallback, static route manager dictionary fallback, and server construction
v7.0.9
- Fixed request timing so
HttpContextBase.Timestampstarts at request entry instead of first lazy access - Switched request/response elapsed timing to monotonic stopwatch-based measurement to avoid wall-clock skew spikes
- Added regression coverage for context timing and retained coverage for pooled HTTP/1.1 request-state reset
v7.0.4
- Merged
Watson.Coreinto theWatsonpackage as a single assembly - The
WatsonWebserver.Corenamespace is preserved for backward compatibility - Core source files now live under
src/WatsonWebserver/Core/ - Consumers install only the
WatsonNuGet package; there is no longer a separateWatson.Corepackage - Existing
using WatsonWebserver.Core;statements require no changes
v7.0.0
Watson 7.0 is a major release that expands the server from an HTTP/1.1-focused model into a unified multi-protocol platform with shared consumer semantics across HTTP/1.1, HTTP/2, and HTTP/3.
WebSockets
- Added native Watson 7 HTTP/1.1 WebSocket support with Watson-owned handshake handling and
WebSocketSession - Added websocket route registration through
server.WebSocket(...), including same-path HTTP and websocket dispatch - Added websocket session enumeration, connectivity checks, and disconnect-by-guid APIs
- Added websocket observability events for session start, session end, and handshake failure
- Added
Test.WebsocketServerandTest.WebsocketClientinteractive sample applications - Added shared websocket coverage in
Test.Shared, surfaced through bothTest.XUnitandTest.Automated - Added initial websocket benchmark coverage in
Test.Benchmark - Added websocket-specific documentation in
README.md,WEBSOCKETS_API.md,MIGRATING_FROM_WATSONWEBSOCKET.md, andTESTING.md
Protocols And Transport
- Added protocol-level configuration through
WebserverSettings.Protocols - Added support in
Watsonfor:- HTTP/1.1
- HTTP/2 over TLS
- HTTP/2 cleartext prior knowledge when explicitly enabled
- HTTP/3 over TLS/QUIC
- Added runtime HTTP/3 availability detection and startup normalization
- Added Alt-Svc emission support through
WebserverSettings.AltSvc - Added HTTP/2 and HTTP/3 connection, request, response, and protocol-processing paths
Consumer Configuration Surface
- Added
ProtocolSettingsEnableHttp1EnableHttp2EnableHttp3EnableHttp2CleartextIdleTimeoutMsMaxConcurrentStreamsHttp2Http3
- Added
AltSvcSettingsEnabledAuthorityPortHttp3AlpnMaxAgeSeconds
- Added HTTP/3 tuning through
Http3SettingsMaxFieldSectionSizeQpackMaxTableCapacityQpackBlockedStreamsEnableDatagram
- Retained and extended
WebserverSettings.IO,Ssl,Headers,AccessControl,Debug, andUseMachineHostname
Validation And Runtime Safety
- Added
WebserverSettingsValidatorprotocol validation - Startup now fails fast when:
- all protocols are disabled
- HTTP/2 is enabled on a transport that does not support it
- HTTP/3 is enabled on a transport that does not support it
- HTTP/2 is enabled without TLS and without explicit cleartext prior-knowledge mode
- HTTP/3 is enabled without TLS
- Alt-Svc is enabled while HTTP/3 is disabled
- When HTTP/3 is configured but QUIC is unavailable at runtime, Watson now disables HTTP/3 and Alt-Svc for that process start rather than advertise unsupported behavior
Request And Response Semantics
- Unified request and response consumption model across protocols through
HttpContextBase,HttpRequestBase, andHttpResponseBase - Added protocol metadata to request and context objects
- negotiated protocol
- connection metadata
- stream metadata
- Clarified chunked-transfer semantics:
- HTTP/1.1 request
ReadChunk()remains available for actual chunked transfer-encoding - HTTP/2 and HTTP/3 requests now explicitly reject
ReadChunk()because those protocols do not expose HTTP/1.1 chunk semantics SendChunk()andSendEvent()remain available across protocols, with HTTP/2 and HTTP/3 using transport-native framing semantics
- HTTP/1.1 request
- Added request trailer support when the protocol permits it
- Added response trailer support when the protocol permits it
- Added
ReadBodyAsync()to make full-body reads explicit and cache-aware
FastAPI-Like API Route Integration (SwiftStack)
Watson 7.0 integrates the SwiftStack REST experience directly into the webserver, providing a FastAPI-like developer experience without requiring a separate library.
- Added
server.Get(),server.Post<T>(),server.Put<T>(),server.Patch<T>(),server.Delete(),server.Head(),server.Options()convenience methods onWebserverBase - Added
ApiRequestwrapper providing typed access to URL parameters, query parameters, headers, and deserialized request body - Added
RequestParametersclass with typed accessors (GetInt,GetGuid,GetBool,GetEnum<T>,TryGetValue<T>, etc.) - Added automatic JSON serialization of handler return values via
ApiResponseProcessornullreturns empty responsestringreturnstext/plain- Objects return
application/json (object, int)tuples set custom HTTP status codes
- Added
WebserverExceptionfor structured error responses mapping to HTTP status codes - Added
ApiErrorResponsewithApiResultEnumfor consistent error payloads - Added middleware pipeline (
MiddlewarePipeline,MiddlewareDelegate) with per-request execution and short-circuit support - Added structured authentication via
AuthenticateApiRequestreturningAuthResultwith automatic 401 responses - Added request timeout support via
WebserverSettings.Timeoutwith cooperative cancellation and 408 responses - Added built-in health check endpoints via
UseHealthCheck()with custom check delegates - Added
RoutingGroupApiExtensionsfor API route registration onRoutingGroupinstances - API routes support all existing Watson features: OpenAPI metadata, exception handlers, pre/post-authentication groups
Routing, Lifecycle, And Extensibility
- Preserved the existing Watson routing pipeline while aligning it with the 7.0 shared protocol architecture
- Continued support for:
- preflight routes
- pre-routing hooks
- pre-authentication routes
- authentication hooks
- post-authentication routes
- default routes
- post-routing hooks
- Retained
HostBuilderfluent configuration support - Added or expanded lifecycle metadata and cancellation handling through
HttpContextBase - Retained
MetadataonHttpContextBasefor application-defined request state
OpenAPI / Swagger
- Added built-in OpenAPI 3.0 document generation
- Added built-in Swagger UI hosting
- Added
UseOpenApi()extension methods onWebserverBase - Added route-level OpenAPI metadata support for documented endpoints
- Added
Test.OpenApicoverage and examples
Performance
The 7.0 optimization program benchmarked each candidate independently and retained only the items that improved throughput without introducing correctness regressions.
Kept optimizations in the 7.0 line:
- Item 3: static-route reads now use frozen snapshots and the normalized path is reused
- Item 4: cached
JsonSerializerOptionsinDefaultSerializationHelper - Item 5: cached serialized header prefixes on the simple-response path
- Item 7: pooled HTTP/1.1 request/response/context objects for keep-alive reuse
- Item 12: lazy header materialization for HTTP/2 and HTTP/3 requests
- Item 17: internal
ConfigureAwait(false)consistency fix on the response path
Optimization candidates that regressed performance or behavior were benchmarked, documented, and reverted before release.
Testing And Tooling
- Added
Test.RestApiinteractive server demonstrating all API route integration features - Replaced
Test.AllwithTest.Automated - Added
Test.XUnitwith unit tests for core types (RequestParameters,MiddlewarePipeline,AuthResult,WebserverException,ApiErrorResponse,TimeoutSettings) - Refactored automated tests to emit:
- per-test pass/fail result lines
- per-test runtime
- final aggregate pass/fail summary
- final failed-test enumeration
- Expanded automated coverage for the higher-risk 7.0 areas, including:
- route snapshot coherency
- serializer behavior
- cached response header paths
- pooled HTTP/1.1 object reset behavior
- HTTP/2 and HTTP/3 lazy header materialization behavior
- Added stable execution scripts and testing documentation for repository contributors
Breaking Changes And Behavioral Changes
- Watson 7.0 should be treated as a major release for consumers
- Protocol enablement is now explicit and validated
- HTTP/2 cleartext use requires explicit prior-knowledge opt-in
- HTTP/3 requires TLS and depends on runtime QUIC availability
ReadChunk()is now explicitly an HTTP/1.1-only API surface- Multi-protocol deployments should prefer protocol-agnostic body reads through
ReadBodyAsync(),Data,DataAsBytes, orDataAsString UseMachineHostnamebehavior remains part of the host-handling model and is forced when wildcard hostnames such as*or+are used
Previous Versions
v6.6.0
- Fixed post-authentication content routes calling the pre-authentication handler
- Fixed
PostRoutingnot being awaited - Fixed static
CancellationTokenSourcesharing across contexts - Added directory traversal protection in content-route file serving
- Added
MaxRequestBodySize - Added
MaxHeaderCount - Added
IDisposablesupport to context, request, and response base classes - Fixed
MemoryStreamleaks on response paths - Improved route-manager and body-read performance
- Replaced route-manager
lockusage withReaderWriterLockSlim - Added preparatory HTTP/1.1 annotations ahead of protocol work
v6.5.x
- Added OpenAPI and Swagger support
v6.4.x
- Minor breaking changes to server-sent events
v6.3.x
- Changed
SendChunkto acceptisFinal - Added server-sent events
- Minor internal refactor
v6.2.x
- Added exception-handler support for static, content, parameter, and dynamic routes
v6.1.x
- Moved
ContentRouteHandlerintoContentRouteManager
v6.0.x
- Major refactor consolidating WatsonWebserver and HttpServerLite concepts
- Consolidated shared types into
WatsonWebserver.Core - Removed attribute routes
- Unified constructors
- Simplified SSL configuration around
X509Certificate2 - Introduced current routing architecture and host-builder changes
v5.1.x
- Added
HostBuilder
v5.0.x
- Moved to
NameValueCollection - Reintroduced header and query helper methods on
HttpRequest
v4.x
- Added parameter routes
- Added response/request data helper changes
- Added route details within
HttpContext - Added improved constructor and hostname behavior
- Added support for unknown HTTP methods
v3.x
- Added and expanded chunked-transfer support
- Moved route callbacks to async
Tasksignatures - Added stream and callback improvements
- Added statistics and multi-listener support
v2.x
- Added pre-routing callback
- Added automatic decoding of chunked inbound requests
- Added request and response stream support
- Simplified constructors and response model
v1.x
- Added static routes, dynamic routes, content routes, whitelist/blacklist behavior, multiple-host support, and early framework portability work