Repository navigation
2.1.2 adds request.rawParams and makes the errors of the framework LocalizedErrors. It is source-compatible with 2.1.x: swift package diagnose-api-breaking-changes 2.1.1 reports no breaking changes.
New: request.rawParams
request.params holds the values of route variables decoded, so a%2Fb/c and a/b/c both give a/b/c for a path variable. request.rawParams has the same names with the values as the client sent them, still percent-encoded and not decoded at all (a + stays a +).
server.get["/files/::path"] = { request in
let decoded = request.params["path"] ?? "" // "a/b/c" for GET /files/a%2Fb/c
let raw = request.rawParams["path"] ?? "" // "a%2Fb/c"
return .ok(.text("\(decoded) was sent as \(raw)"))
}A variable :name gets its raw segment, and a path variable ::name its raw segments joined with /. As in params, empty segments are left out, a path variable that matches nothing has the value "", and the query is not part of a value. Like params, it is set when the request has been routed: in handlers, and in middleware after next has returned. A raw value is untrusted input: decode it at most once, and never use it as a file path without checking it.
Routers: the protocol NanoHTTPRouter has a new requirement routeWithRawParams(_:path:) with a default implementation, so existing routers keep working (their rawParams stay empty). NanoHTTPSegmentRouter implements it.
New: errors are LocalizedErrors
All error types (NanoHTTPError, NanoSocketError, NanoHTTPParserError, NanoHTTPRouterError, NanoFileError, NanoHTTPResponse.ResponseError, NanoWebSocketSession.WsError and .Control) now say what failed in error.localizedDescription, instead of Foundation's generic text:
Unable to bind the socket to the address: Address already in use
404 Not Found: There is no item 7
The request line is not of the form METHOD TARGET VERSION: "BAD"
The texts are in English. Text that a client sent is quoted and escaped in them, so a control character cannot get into a log. description and string interpolation ("\(error)") are unchanged, and the server still answers every error but a NanoHTTPError with a 500 without details.
Notes on upgrading
- A subclass of
NanoHTTPSegmentRouterthat overridesroute(_:path:)to change how requests are routed has to overriderouteWithRawParams(_:path:)instead: the server now calls that function. - If your program declares
extension NanoSocketError: LocalizedError(or the same for another of these types) itself, remove it.
Other
- Router lookups of paths without percent-escapes are a little faster; paths with escapes take about 0.1–0.15 µs longer. Paired benchmarks against 2.1.1 show no difference in throughput or latency.
- The tests of
NanoProcessTeststhat send a signal to the test process are skipped under a debugger: lldb (and so Xcode) stops the process atSIGUSR1/SIGUSR2, and the test run seemed not to end.
Install: .package(url: "https://github.com/objecthub/swift-nanohttp.git", from: "2.1.2")