Skip to main content

relic_headers 2.0.0-rc.5 copy "relic_headers: ^2.0.0-rc.5" to clipboard
relic_headers: ^2.0.0-rc.5 copied to clipboard

HTTP header names and stores shared by Relic adapters and other packages.

2.0.0-rc.5 #

  • feat: relic_native takes client certificates, encrypted and PKCS#1 private keys and v6Only, selects http/1.1 through ALPN, and an IPv6 listener takes IPv4 clients. The core packages are unchanged and released in step

2.0.0-rc.4 #

  • fix: relic_native runs on Windows. The core packages are unchanged and released in step

2.0.0-rc.3 #

  • feat!: Replace the request stream with an exchange-based Adapter
    • BREAKING: Adapter is an interface with listeners, capabilities and start(sink). It hands over AdapterExchange objects with respond, hijack, upgradeWebSocket and abort. Adapter.requests, Adapter.port and AdapterRequest are gone. The port is on listeners and on RelicServer.port. The toolkit for writing an adapter is in package:relic_core/adapter.dart
    • BREAKING: IOAdapter.port, requests, respond, hijack, connect and IOAdapterRequest are gone
    • BREAKING: HttpResponseExtension.applyHeaders(headers, body) is applyFraming(headers, framing)
    • BREAKING: HijackCallback receives a StreamChannel<Uint8List>
    • BREAKING: hijack throws HijackRefused when the request body is chunked and not read to its end
    • BREAKING: Request.protocolVersion is Request.protocol, an HttpProtocol
    • BREAKING: RelicWebSocket implementers provide done, and tryClose accepts 1001
    • BREAKING: RelicServer.close() waits for the exchanges in flight and sends 1001 to every WebSocket. close(grace:) forces the close after a deadline. close(force: true) ends a graceful close that is still waiting. RelicApp.close takes the same force and grace
    • The adapter conformance suite in test_utils runs against any adapter
  • feat!: Rebase Headers on HeaderStore
    • BREAKING: Headers and MutableHeaders are no longer Maps. Read with headers[name], headers(accessor), get or tryGet. Write with Headers.build, transform, and MutableHeaders.set, add, remove and assign. The Headers.x[headers] form, the Header extension type and HeadersBase are gone
    • BREAKING: Headers.fromMap throws FormatException for a name that is not a token or a value with CR, LF or NUL
    • BREAKING: HeaderAccessor takes a HeaderName. ReadOnlyAccessor has an abstract decode, and an accessor built from a function extends FunctionAccessor
    • BREAKING: Request.target holds the path and query as a RequestTarget. An adapter answers 400 to a malformed one
    • New package relic_headers, re-exported by relic_core: HeaderName, HeaderStore, MutableHeaderStore, MapHeaderStore and ByteHeaderStore. HeaderName.custom takes a lowercase token
    • The Headers.xHeader string constants are deprecated in favour of HeaderName.x
  • feat!: The Body frames every response
    • BREAKING: Content-Length, Content-Type and the chunked coding come from the Body. Setting them on the response headers has no effect
    • BodyType.fromContentType and the Headers.contentType accessor are public
    • A HEAD request gets the same Response as GET. The adapter sends its length and type and no body
  • fix!: A HEAD request to a path without a HEAD route runs its GET route (RFC 9110 9.1)
    • BREAKING: Router.lookup(Method.head, ...) returns the GET route of such a path, and MethodMiss.allowed lists HEAD beside GET. A GET handler that must not run on HEAD checks request.method
    • BREAKING: RouterMatch has no public constructor, and LookupResult takes T extends Object
    • A Hijack or WebSocketUpgrade answering such a HEAD gets 405. RouterMatch.headFallback marks the match and RouterMatch.registered lists the path's own methods
  • perf!: A sync response reaches the adapter without a Future, and a ContextProperty takes its slot once
    • BREAKING: The routing handler and respondWith return a sync handler's Response as is. A handler that throws before its first await throws to the caller
    • BREAKING: A ContextProperty holds its slot for the life of the isolate. Create each one once, as a global
  • perf: Typed headers decode from the wire bytes. HeaderCodec.bytes and HeaderCodec.fields take a parser over bytes. HeaderCodec.single and the text constructors stay
  • feat: New package relic_native, a Relic adapter on a Zig HTTP server
  • feat: FramedWebSocket frames RFC 6455 over any StreamChannel<Uint8List>. The server upgrades through the adapter when capabilities.webSocket is set and frames over hijack otherwise. With neither it answers 501
  • feat: The Body constructor is public and takes bytes, stream or open. A body built with open opens only when read. read(maxLength:) rejects a known oversize body without reading it, and a rejected upload gets its answer instead of a reset
  • feat: Body.bytes, Body.readAll(), Body.consume and httpDate()
  • feat: httpDate, logMessage and logRequests read the time through package:clock, so withClock controls them
  • fix: A response head carries Connection: close when the connection closes after it (RFC 9112 9.6)
  • fix: A 206 range response defaults its Content-Type to application/octet-stream
  • fix: A WebSocketUpgrade answers a request other than GET with 405
  • fix: RelicApp.run(backtrack: false) and routeWith(backtrack: false) look routes up without backtracking
  • fix: Request.forwardTo keeps the backtrack and useHostWhenRouting options of the original

2.0.0-rc.2 #

  • feat!: Add HTML form and multipart parsing (#380) - closes #379
    • BREAKING: The minimum Dart SDK is 3.10.0. The Dart 3.9.0 compiler crashes in the FFI transform (dart-lang/sdk#61321)
    • BREAKING: BodyType has no const constructor. Drop const from BodyType(...) calls
    • BREAKING: Extended Content-Disposition parameters such as filename* are RFC 8187 ext-values and always encode as UTF-8. ContentDispositionParameter has no encoding, and its language is a LanguageTag. Parsing throws FormatException for a charset other than UTF-8 and for a malformed ext-value
    • Add req.urlEncodedForm(), req.multipartForm() and req.formData(), which picks the parser from the request Content-Type
    • Add req.multipart() to stream parts without aggregating them. Each part is a MultipartFieldPart, MultipartFilePart or MultipartOtherPart
    • Read fields through accessors such as IntFormField('age') with form.fields.get, tryGet and getAll, and files through FormFile. A missing field throws MissingFormFieldException, a value that does not decode throws InvalidFormFieldException
    • FormLimits caps body size, part, field and file counts, and field and file sizes. Going over one throws FormLimitExceededException, whose limit names the FormLimit
    • Uploads go to MemoryUploadStorage by default. TempUploadStorage in relic_io writes each upload to its own directory. On POSIX systems the directory has mode 0700. On Windows it inherits the permissions of its parent, and the default parent, the user's temp directory, is private to that user. Call MultipartFormData.dispose() to delete them
    • Upload filenames are reduced to their basename, with control and bidi formatting characters removed. ., .. and an empty filename give a null filename. filename* is ignored, per RFC 7578
    • The server answers an uncaught FormException with its statusCode, which is 400, 413 or 415. When parsing fails it also sends Connection: close, as the rest of the body may be unread
    • BodyType carries Content-Type parameters such as boundary in parameters. Body.fromData and Body.fromDataStream take a parameters argument, and the dart:io adapter carries them through
    • Add a typed ContentTypeHeader, read with headers.contentType. Set Content-Type through the body

2.0.0-rc.1 #

  • refactor!: Drop NormalizedPath interning (#375) - fixes #118, #342, closes #344
    • BREAKING: NormalizedPath.interned is removed. Construction no longer caches, so there is no per-isolate cache to size, and no input that can thrash it
    • Add Router.lookupUri(method, url), the entry point for request routing: it derives the path with NormalizedPath.fromUri and looks it up with lookupPath
    • Routing recovers most of the lost throughput by pre-computing repeated work and by undoing parameter bindings in place while backtracking, instead of copying the parameter map at every level
  • fix!: Address security audit findings (#369)
    • BREAKING: Cross-origin WebSocket upgrades are rejected with 403 by default; pass WebSocketUpgrade(..., allowAnyOrigin: true) to accept them. Only the host is compared, since a TLS-terminating proxy changes scheme and port
    • BREAKING: Header names and values are validated on assignment. CR, LF, NUL, and invalid names now throw where every header write funnels, rather than reaching the wire
    • BREAKING: Malformed auth headers and non-token MIME type parts are rejected where they were previously tolerated
    • The request path is split into segments before percent-decoding, so an encoded separator (%2F) can no longer introduce a path boundary that no upstream proxy saw; NormalizedPath.fromUri names the safe conversion
    • The path is normalized before the routing host is prepended, so a path resolving upwards can no longer pop the host and select another virtual host
    • Auth headers are parsed with the linear header scanner: one pass with no quadratic backtracking on a long value, and text between auth-params is rejected instead of skipped
    • Content-Disposition parameter values and AuthenticationHeader challenge parts are escaped and validated, so a quote in a filename or realm can no longer end the value and graft on another parameter or challenge
    • The token grammar is enforced on MIME type parts, which io.ContentType took separately and thus bypassed the CR/LF check applied to ordinary header values
    • Multi-range responses are streamed lazily and the range count is capped, so a short request can no longer ask for many times the file size
    • Multipart boundaries are drawn from a cryptographic generator instead of ~20 bits from Random
    • The adapter dispatch is awaited, so a response that fails to write yields a 500 instead of leaving the connection open and the client waiting
    • Detached (hijacked and upgraded) connections are tracked by the adapter: counted by connectionsInfo(), drained and sent a 1001 close on graceful shutdown, and destroyed on close(force: true)
    • use() on a catch-all route now applies to the prefix itself, so /api no longer bypasses the middleware that /api/keys runs
    • Add Token68 for the RFC 9110 token68 form, used when validating a single-token WWW-Authenticate challenge
    • docs: The static file handler never filtered hidden files; the documentation no longer claims it does. Every file in the served directory is served, dot files included

2.0.0-beta.1 #

  • feat: Add CacheControlHeader.parseStrict for validating own values (#370)
    • Throws a FormatException for an unrecognized directive or a malformed delta-seconds value instead of ignoring it
    • Intended for values under the sender's own control, such as server configuration; parse remains lenient per RFC 9111 5.2

2.0.0-beta.0 #

Overhaul of typed HTTP headers for RFC compliance, landing in concert with serverpod 4.0. Parsing of received (request) headers is lenient (except security-sensitive ones), while construction and serialization are always strict. Many typed headers changed shape and/or semantics, so this is a breaking release.

  • refactor!: Cookie and Set-Cookie headers (#361)
    • BREAKING: SetCookie now represents a single cookie, and SetCookieHeader is a List<SetCookie> collection (one Set-Cookie line per cookie, RFC 6265 4.1). The previous single-cookie SetCookieHeader(name:, value:, ...) API is replaced by SetCookie(...); augment a response with mh.setCookie = (mh.setCookie ?? const SetCookieHeader.empty()).add(cookie)
    • The request Cookie header is parsed leniently: a malformed cookie is skipped and the header is rejected only when no cookie in it is usable
    • Add CookieHeader.getCookies(name) returning every cookie with that name in order; byte-identical duplicates are preserved (not collapsed)
    • Set-Cookie decode is strict (it is produced by the server): a malformed attribute rejects the cookie
    • Domain is normalized per RFC 6265 5.2.3 — the full leading-dot run is stripped and the host is lower-cased; an all-dots Domain is rejected
    • Max-Age is parsed as a strict decimal integer per RFC 6265 5.2.2; non-decimal values such as 0xFF are rejected
    • Nameless =value segments are dropped when parsing the request Cookie header
  • feat!: RFC compliant typed headers (#360) — fixes #113, #142
    • Many typed headers changed their Dart interface and/or their parse/serialize semantics
    • Parsing is lenient on receive; construction and serialization are strict

1.2.0 #

  • feat: Make NormalizedPath interning cache configurable (#343)
    • Introduce abstract Cache<K, V> interface
    • Add NoCache implementation for high-cardinality workloads
    • LruCache now implements Cache
    • NormalizedPath.interned can be swapped to any Cache implementation
  • feat: Add staticChangeCount and VM service extension to DeveloperTools (#341)
  • feat: Add DeveloperTools class to RelicApp (#340)

1.1.1 #

  • docs(ai): Adds skills for AI agents based on documentation. (#338)

1.1.0 #

  • feat: Allow internal request forwarding with req.forwardTo(newReq) (#331)
  • feat: Add indexAssets() and tryAssetPathSync() to CacheBustingConfig (#332)
  • feat: Auto-index assets in StaticHandler when cache busting is configured (#332)

1.0.0 #

Relic is now considered stable and production-ready! 🎉

0.15.1 #

  • fix: Downgrade meta dep to ^1.16.0 to match flutter 3.32.0 (serverpod lower bound) (#325)

0.15.0 #

  • feat: Add virtual host routing support (#322)
    • Add useHostWhenRouting parameter to routeWith() middleware
    • Add useHostWhenRouting parameter to RelicApp
    • When enabled, routing uses {host}{path} for route matching
  • feat: Add paths, toString(), and toDot() to PathTrie for debugging (#320)
  • feat: Add force parameter to server close() method (#317)
  • refactor: Restructure into multi-package workspace with relic_core, relic_io, and relic packages

0.14.0 #

  • feat!: Add optional consume flag to attach (#309)
    • BREAKING: attach now throws ArgumentError when called with a tail path (/**), unless consume: true and the attached trie/router has a single value at the root (isSingle)
    • BREAKING: group now throws ArgumentError when called with a tail path
    • Add consume flag to attach that resets the attached trie's root after attachment
    • Add isSingle property to check if a trie/router has only a single root value/route
    • Allow attach(..., consume: true) at tail paths (/**) when the attached trie/router isSingle
    • Update injectAt to use attach(..., consume: true), still enabling injection at tail paths for simple HandlerObjects (those adding a single handler at the root ('/'))

0.13.1 #

  • fix: Close connection, if request too large (#303)

0.13.0 #

  • feat!: Add maxLength argument on read (#301)

0.12.0 #

  • feat!: Support back-tracking during routing (#297)
  • fix: Ensure close is idempotent (#295)

0.11.0 #

  • feat!: Add typed accessor for query and path parameters (#288)
  • feat: Introduce ConnectionInfo (#273)
  • feat: Add IPAddress class (independent of dart:io) (#272)
  • refactor!: Simplify ContextProperty interface
  • refactor!: Disallow url rewriting in Request.copyWith (#289)
  • refactor!: Use named ctors on all header classes (#283)
  • refactor!: Avoid repeating ctor name on parameter (#282)
  • fix!: Remove stale arguments from Request and Response class (#274)
  • fix: Don't overwrite Content-Length when set as header (#291)

0.10.0 #

  • refactor!: The Great Simplification (#264)
    • Merged RequestContext into Request by moving the token property
    • HandledContext renamed to Result
    • Merge ResponseContext into Response (now implements Result)
    • Removed respond(), hijack(), and connect() methods - handlers can construct and return Results directly
    • Updated handler signatures: Handler = FutureOr<Result> Function(Request req)
    • Consolidated context classes into single file using part files
    • Updated all examples and tests
    • Significant simplification of the class hierarchy by eliminating the:
    • Context,
    • RequestContext,
    • RespondableContext,
    • HijackableContext,
    • ConnectableContext, and
    • ResponseContext interfaces
    • Renamed ConnectionContext to WebSocketUpgrade (now extends Result)
    • Renamed HijackedContext to Hijack (now extends Result)

0.9.2 #

  • feat: Expose noOfIsolates parameter on serve extension on RelicApp (#260)
  • feat: Add injectAt extension method on Router<T> (#261)
  • feat: Allow re-run of RelicApp.run after close (#257)

0.9.1 #

  • feat: Add async RelicServer.connectionsInfo() method (#255)
    • Adds a connectionsInfo() method to RelicServer that returns the current number of active, closing, and idle connections.
    • A new ConnectionsInfo typedef is introduced as a record type with active, closing, and idle fields.

0.9.0 #

  • refactor!: Context renaming (#251) Renames core context types for improved clarity and consistency:
    • NewContext → RequestContext
    • ConnectContext → ConnectionContext
    • HijackContext → HijackedContext
    • Base class RequestContext renamed to Context
  • chore!: Upgrade sdk to ^3.7.0 (#239)
  • feat: Introduce MultiIsolateRelicServer (#216) Implements multi-isolate support for RelicServer to enable concurrent request handling across multiple CPU cores. Adds noOfIsolates optional named parameter to RelicServer constructor, and RelicApp.run.
  • fix: Mask sensitive credentials in authorization header toString() methods (#238)

0.8.0 #

  • feat!: RelicApp now supports hot-reload (#226)
  • feat: Introduce RelicApp (#212)
  • feat: Introduce MiddlewareObject (#211)
  • feat: Introduce HandlerObject (#210)
  • feat(router): Add fallback property for unmatched routes (#196)
  • feat(router): Add asHandler extension to use Router
  • feat: Adds support for cache busting (#192)
  • feat: Support mime-type inference (#206)
  • feat: Add NewContext.withRequest convenience method (#198)
  • fix: Build platform correct path when serving files. (#207)

0.7.0 #

  • feat(router): Add support for setting up mappings of values on lookup router.use(path, map) (#186)
  • feat(trie): Add support for setting up mappings of values on lookup trie.use(path, map) (#185)

0.6.0 #

  • feat!: Custom CacheControl header per file (#167)
  • feat!: Distinguish between path and method miss in router lookups (#179)
  • feat!: Remove automatic X-Powered-By header (#169)
  • feat!: Remove unused strict flag (#181)
  • feat(router): Router.group (#157)
  • feat: Add operator== and hashCode on all header classes (#155)
  • fix: HEAD request should match GET except for body, including Content-Length (#180)
  • fix: Host header is not a Uri. Introduce an RFC3986 compliant HostHeader class (#142)
  • fix: Rip out Router.staticCache (#172)
  • fix: Set content length on body, not headers (#161)

0.5.0 #

  • refactor!: Rename withResponse to respond (matches connect/hijack) (#134)
  • docs: Adds a docusaurus documentation page for relic. (#132)
  • refactor!: Static File Handler Overhaul (#127)

0.4.1 #

  • fix: Export bindHttpServer in io_adapter.dart (#114)
  • fix: Handle ':' in BasicAuthorizationHeader parser correctly (#112)

0.4.0 #

  • fix: Missing convenience getters and setter for Headers.xForwardedFor (#108)
  • refactor!: Get rid of old context map on Message (Request/Response) (#105)
  • feat: X-Forwarded-For typed header (#107)
  • feat: Add ContextProperty class (wraps Expando) (#94)
  • feat: Typed forwarded header (#101)
  • build(deps): Bump cli_tools from 0.5.1 to 0.6.0 (#100)
  • refactor!: Replace DuplexStreamChannel with RelicWebSocket (#91)
  • test: Add headers constants test and rename file (#89)
  • build(deps): Bump lints from 5.1.1 to 6.0.0 (#92)
  • fix: Fix request/response header sets (#90)
  • docs: Update router docs (#88)
  • docs: Update router entry comment (#87)
  • feat: WebSocket support (#84)
  • feat: Store benchmark results with git notes (#79)
  • feat: The routeWith middleware builder function is now generic. (#78)
  • feat(Handler)!: Signature changed (#76)
  • feat: Add Router.isEmpty getter (#75)
  • docs: Add CONTRIBUTING.md and CODE_OF_CONDUCT.md (#69)
  • feat: PathTrie wildcard and tail matching support (#70)
  • feat: Router middleware (#68)
  • feat!: Router now supports verb directly (#65)
  • docs: Add badges for codecov, etc. (#67)
  • feat: Add addOrUpdate, update, and remove to PathTrie (#63)
  • feat: Support Router.attach (#62)
  • feat: Allow a trie to be attached as a subtrie to another (#61)
  • feat: Router class (#52)
  • refactor!: Decouple from dart:io and avoid using exceptions for control-flow (#48)
  • chore: Add serverpod lints (#46)
  • feat!: Replace HeaderDecode with HeaderCodec to allow customization on encoding as well (#43)
  • fix: Ensure cache is updated immediately (#42)
  • feat!: Support typed access to custom headers (#38)
  • ci: Hoist continue-on-error to job (#37)
  • ci: Add test coverage (#36)
  • fix!: RelicServer cannot reliably know the Uri to use to hit it (#32)
  • chore: Automate publishing to pub.dev when semver tag is created (#31)
  • chore: Add pull request title validation. (#30)
  • refactor!: Get rid of RelicAddress. (#29)

0.3.0 #

  • feat: Implements lazy loading when parsing headers to avoid unnecessary validation.
  • feat: Makes address strongly typed and adds RelicAddress type.
  • fix: Resolves issue with Content-Length header conflicting with Transfer-Encoding: chunked.

0.2.0 #

  • First tech preview.

0.1.0 #

  • Initial version.
0
likes
160
points
13k
downloads

Documentation

API reference

Publisher

verified publisherserverpod.dev

Weekly Downloads

HTTP header names and stores shared by Relic adapters and other packages.

Homepage
Repository (GitHub)
View/report issues
Contributing

Topics

#server #web #http

License

BSD-3-Clause (license)

More

Packages that depend on relic_headers