Skip to content

Apion 0.2.0

Choose a tag to compare

@edadma edadma released this 05 Jul 03:01
· 2 commits to stable since this release

A hardening release. Breaking changes — no backward compatibility with 0.1.0.

Added

  • Multi-valued query and form parsing (Map[String, Seq[String]]) with queryParam / formField first-value accessors
  • Type-safe request context via TypedKey[A] / Context, replacing the untyped Map[String, Any]
  • Per-server configuration via ServerConfig (default headers, body size, read timeout); Server(config)
  • Route helpers head, options, all, and single-segment * wildcard matching

Fixed

  • decodeURIComponent corrupted multi-byte UTF-8 (it decoded one char per %xx byte); now uses the JS runtime, with +-as-space handled for query/form
  • Request body could be re-read after Request.copy reset its promise; the body is now memoised on the connection and consumed exactly once
  • Multiple WWW-Authenticate headers were overwritten (a typo in the multi-value header set)
  • AuthMiddleware.excludePaths auth-bypass: matching is now segment-aware on request.path (was url.startsWith, which matched the query string and character-prefixes like /publicfoo against /public)
  • Multi-segment sub-router mounts (use("/api/v1", r)) only stripped one segment
  • The router froze its route table on the first request, silently ignoring later registrations
  • Wildcard (*) routes never matched (the matcher had no wildcard case)

Changed

  • Default response headers are applied per-server at the send boundary rather than baked into Response factories
  • The router is documented as the ordered pipeline it is (removed the "pre-compiled matching" framing)

Removed

  • Response.configure / Response.resetDefaultHeaders and the global default-header var — configure via ServerConfig
  • Global mutable Request.maxBodySize / Request.bodyTimeout vars — now val fallbacks; set defaults via ServerConfig
  • InternalComplete from the public Result type (the router uses an internal Outcome)

Migration notes

  • request.query / request.form are now Map[String, Seq[String]] — use request.queryParam(name) / request.formField(name) for the first value
  • Middleware context: replace request.context + ("k" -> v) with request.context.updated(key, v) where key: TypedKey[V]; read with request.context.get(key)
  • Default headers / body limits: replace Response.configure(...) and Request.maxBodySize = ... with Server(ServerConfig(...))

Full changelog: https://github.com/edadma/apion/blob/v0.2.0/CHANGELOG.md

204 tests, clean under -Werror.