Skip to content

Releases: voidrunner3074/aastro

0.11.1

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 03 Oct 15:14
4f3b920

Fixed

  • http2: off broke every TLS connection with an HTTP/2-capable peer instead of pinning it to HTTP/1.1 - on the
    data port clients got the connection dropped mid-request, on an upstream every request failed with 502. off only
    restricted http.Server/http.Transport.Protocols, while the TLS config still hardcoded ALPN
    NextProtos: [h2, http/1.1], so the handshake kept negotiating h2 that the HTTP layer then couldn't speak. ALPN
    now advertises only http/1.1 when http2: off, on both the server and the upstream side. auto and on are
    unaffected, as is anything without TLS (no ALPN there, so no HTTP/2 to negotiate in the first place).

0.11.0

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 03 Oct 13:11

Added

  • http2: auto | on | off on gateway.server and per-upstream transport. auto (the default)
    is exactly today's behavior: HTTP/2 negotiated over TLS, HTTP/1.1 otherwise - existing configs
    are unaffected. off pins either side to HTTP/1.1 even when TLS is on - the escape hatch for a
    backend with a flaky HTTP/2 stack, or a quick killswitch on the data port (e.g. for HTTP/2 Rapid
    Reset-style concerns) without touching TLS config. on requires tls.enabled at the same scope
    • the gateway has no cleartext HTTP/2 (h2c) support - and is rejected by config validation
      otherwise.

Changed

  • Internal: upstream transports now set HTTP/2 via http.Transport.Protocols instead of the
    deprecated golang.org/x/net/http2.ConfigureTransport, dropping the direct dependency on
    golang.org/x/net (now indirect-only, pulled in transitively). Not user-facing by itself -
    http2: auto behaves exactly as before - but it's what made the explicit on/off knob above
    straightforward to add on the client side; the data port gets the equivalent treatment via the
    same http.Server.Protocols field.

0.10.0

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 27 Aug 22:25
211a21e

Fixed

  • Retries never fired for an upstream without an explicit method: - retry_on_statuses/timeout retries were
    silently a no-op for the common case of relying on the flow's own method. shouldRetry judged idempotency against
    the raw (often empty) config value instead of the effective method used for the actual request. (The 0.9.0 entry
    below describing this as fixed was itself wrong: the switch cases changed, but the call site never did.)
  • The TE response header was never stripped despite being listed in the hop-by-hop set - the map key was the literal
    string "TE", but net/http always stores and iterates response headers in net/textproto canonical form, which
    for TE is Te (no hyphen to separate words, so only the first letter is capitalized). The lookup silently missed
    every time, leaking the header to the client. Every other entry in that set was already canonical.
  • policy.header_blacklist entries were matched by exact string, not canonicalized - header_blacklist: ["x-secret"]
    silently never blocked a response header that net/http (correctly) stores as X-Secret. Same root cause as the
    TE fix above: HTTP header names are case-insensitive, but the code was comparing them as case-sensitive strings.

Changed

  • Breaking: flow option passthrough renamed to streaming (config field, OpenAPI x-aastro extension, and
    aastroctl openapi import --mode). Existing configs and specs must rename passthrough: true to streaming: true
    before upgrading.
  • Breaking: a flow with exactly one upstream is no longer wrapped in the JSON response envelope. Its upstream's
    status, headers, and body are now forwarded to the client as-is - on success, and on a client error or redirect
    (2xx/3xx/4xx), including bodies that aren't valid JSON, which previously got swallowed into an
    UPSTREAM_CLIENT_ERROR/UPSTREAM_REDIRECT envelope. Only a genuine gateway-side failure (upstream unavailable,
    5xx, timeout, policy violation) still returns a gateway-authored error body - see the envelope removal entry
    below for its current shape, which by the end of this release also covers multi-upstream flows. Single-upstream
    flows are now handled by their own dispatch path, bypassing the scatter/aggregate machinery entirely - see
    Router.dispatch/Router.buildProxyResponse.
  • aggregation is no longer required for a single-upstream flow, since it's never read for one - only a flow with
    more than one upstream must declare it (config validation enforces this in place of the old struct-tag check).
  • aastroctl openapi import --mode envelope renamed to --mode proxy, matching the response shape above; scaffolded
    (single-upstream) flows no longer get a meaningless aggregation: {strategy: array} block.
  • Internal: the several independent switch statements over the upstream error classification (retry eligibility,
    circuit breaker signal, policy applicability, client error code) were consolidated into one table
    (kindTable in upstream_error.go), checked exhaustive at startup. Not user-facing, but worth knowing if you're
    extending upstream error handling: add the new kind's row there rather than hunting down every switch.
  • Breaking: the {"data": ..., "errors": ..., "meta": ...} envelope is gone entirely, including for
    multi-upstream (aggregating) flows - a client no longer unwraps a gateway-specific shape to get at the payload:
    • A full or partial (206, bestEffort) success returns the aggregated data itself as the body - exactly the
      merge/array/namespace result, nothing wrapping it. Which upstreams failed on a partial success moves to
      the X-Partial-Errors response header (one value per failure, e.g. UPSTREAM_UNAVAILABLE) instead of an
      errors body field.
    • A response with no data at all - every upstream failed, or the request was rejected before reaching one
      (rate limit, payload too large, plugin failure, single-upstream gateway failure) - is now an
      RFC 9457 Problem Details document (application/problem+json):
      {"type": "about:blank", "title", "status", "detail"?, "errors": [...]}. type is always the literal
      "about:blank" - RFC 9457's own placeholder for "no further-specific type" - never a real URI, deliberately:
      a dereferencable type link is reconnaissance, since it names the gateway software fronting the request and
      invites probing for what that implies about the backend. errors is the machine-readable discriminator instead
      (always present, one entry per distinct underlying ClientError - more than one only for a multi-upstream
      failure with several different causes); title is a human summary of the highest-priority one and may change
      wording over time. ClientResponse/ResponseMeta are removed from the Go API; WriteError and the
      OpenAPI-generated schemas both moved to ProblemDetails.
    • Request correlation is unaffected by this - it was already carried solely by the X-Request-ID response
      header, never duplicated into a body field.
  • Breaking / security fix: builtin/middlewares/auth's default realm - sent in the WWW-Authenticate header on
    every 401 the gateway itself returns - changed from "aastro" to "restricted". Scope note: this is about the
    gateway's own runtime response to a client. OpenAPI export output and anything that only affects tracing/metrics
    (e.g. gateway.service.name) are a separate concern, owned by whoever runs and publishes them - not touched here.

0.9.0

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 09 Aug 16:11

Added

  • policy.follow_redirects - per-upstream option controlling whether the gateway follows upstream redirects. Defaults
    to false: a 3xx is now propagated to the client instead of being chased. Set it to true to restore the previous
    behavior, keeping in mind that the redirect is followed with the upstream's own TLS configuration and that Go strips
    Authorization and Cookie on cross-host hops.
  • New client error codes UPSTREAM_CLIENT_ERROR and UPSTREAM_REDIRECT, distinguishing an upstreams answer to the
    client from an upstream failure.

Changed

  • Upstream responses are now classified by status class rather than the single >= 500 check. 5xx and transport
    failures remain gateway failures (502, upstream body dropped); 3xx and 4xx are treated as answers addressed to the
    client.
  • Single-upstream flows propagate the upstream status verbatim - a 404, 401, or 302 from the upstream now reaches the
    client as a 404, 401, or 302. Aggregating flows are unaffected: a status is only propagated when every failed upstream
    agreed on it, otherwise the response stays 502.
  • allowed_statuses is now enforced as a contract in both directions: a status on the list is always a success (its
    body flows into data), and a status outside a non-empty list is a policy violation returning 502
    UPSTREAM_MALFORMED, even for statuses that would otherwise be propagated.
  • Client errors and redirects no longer count as circuit breaker failures - a burst of 404s can no longer take a healthy
    upstream out of rotation.
  • Responses with statuses that cannot carry a body (204, 304) are no longer wrapped in the JSON envelope.
  • Upstream policy validation is skipped for transport-level failures, which previously produced misleading
    empty body not allowed and status 0 not in allowed list messages on timeouts.

Fixed

  • A single-upstream flow returned 200 with the upstream's error body when the upstream answered 404, 401, or any
    other non-2xx status outside allowed_statuses. Clients received a success for a request that failed.
  • The circuit breaker reset itself with the very request it rejected: a denied call was recorded as a success, so an
    open breaker closed after blocking a single request instead of staying open until reset_timeout.
  • Retries never fired for upstreams without an explicit method:. Retry eligibility was judged against the raw
    configured method rather than the effective one, so the empty default was never considered idempotent.
  • Empty upstream bodies (204, or 200 with no content) were reported as UPSTREAM_MALFORMED during aggregation, turning
    a successful fan-out into a 206 partial response.
  • Aggregation error responses now carry the retried status correctly; an aborted read no longer produces a
    redirect-shaped errors entry for legitimately empty 3xx bodies.

0.8.0

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 07 Aug 16:32

Added

  • aastroctl openapi import — generate a gateway configuration from an OpenAPI 3.x document. Documents produced by openapi export --extensions are reconstructed losslessly: flows, aggregation, upstreams, policy, and transport are restored, with default-valued fields elided for a minimal, human-readable result. Foreign documents are scaffolded as single-upstream flows, with hosts taken from --default-host or servers[]. Passthrough flows are detected from streamed / responses, and the rate limiter is inferred from 429 responses. Secrets are never restored: plugin/middleware configs and TLS certificate paths are reported as warnings for manual re-adding. The generated config is validated before output, so import never emits a config the gateway would reject.

0.7.0

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 18 Jul 07:47

Added

  • Support for the HTTP QUERY method.
  • aastroctl openapi export — generate an OpenAPI 3.1 (or 3.0) document from a gateway configuration. Response statuses are derived from the actual config: 206 only for best-effort multi-upstream flows, 409 only under on_conflict: error, 429 only when the rate limiter is enabled. Flows guarded by the builtin auth middleware get a bearerAuth security scheme and a 401 response. Passthrough flows are modeled as streamed */* responses. Optional --extensions flag embeds x-aastro snapshots for future config round-trip (middleware configs and secrets are never serialized). Deterministic output, git-friendly. The config is loaded through the same pipeline as the gateway, so the command doubles as a config validator.

Changed

  • Client IP is now extracted only from trusted sources: X-Forwarded-For and X-Real-IP are honored only when the request comes from a trusted_proxies peer, with right-to-left XFF parsing. Prevents rate limiter bypass and client IP spoofing via forged headers.

0.6.0

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 05 Jul 10:26
68d38e5

Added

  • Hot reload of TLS certificates. Aastro watches the directories of the configured cert_file,
    key_file, and ca_file paths and atomically swaps the in-memory material
    when they change. New TLS handshakes use the new certificate; in-flight
    connections are unaffected. No configuration change is required — rotation
    works on the existing cert paths.

    Directory-level watching handles both atomic file replacement on a host
    (write-to-temp-then-rename) and Kubernetes secret mounts, where the projected
    files are updated via symlink swap rather than in-place writes. Certificate
    rotation through cert-manager, Vault Agent, or SPIFFE/SPIRE sidecars is now
    hands-off.

    Reloads are validated before they are applied: if a new certificate or CA
    bundle on disk fails to parse, the error is logged and the previously loaded
    material stays live, so a malformed rotation cannot take the listener down.

0.5.1

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 19 Jun 09:04

Fixed

  • Retries: retry_on_statuses is now honored for 5xx responses. Previously any
    status ≥ 500 was coerced into an error and retried unconditionally, ignoring the
    configured status list. 5xx and non-5xx are now governed by the same rule.
  • Retries: non-retryable failures (internal, body_too_large, policy_violation,
    circuit_open, canceled, read_error) are no longer retried — they previously
    looped until max_retries was exhausted with no chance of a different outcome.
  • Upstream errors: response body and headers of 5xx responses are no longer
    discarded. They are now read and preserved on the upstream response, so error
    detail is available to logging and downstream handling.

Added

  • Retries: idempotency guard. Status-based retries now apply only to idempotent
    methods (GET, HEAD, OPTIONS, TRACE, PUT, DELETE). Non-idempotent requests (e.g. POST, PATCH)
    are no longer replayed on a retryable status, preventing duplicate side effects.
    Transport-failure retries are unaffected.

Changed

  • Retries: retry decision logic consolidated into a single explicit rule.
    Transport-level failures (timeout, connection) are always retryable;
    status-based retries are driven solely by retry_on_statuses; everything else
    is terminal.
  • Used goccy/go-json instead of stdlib encoding/json

0.5.0

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 26 May 17:23

Added

  • New command-line interface and ctl for stub plugins initialization. For more information about the CLI, see the documentation.

Changed

  • Project was renamed from Kono to Aastro

0.4.1

Choose a tag to compare

@voidrunner3074 voidrunner3074 released this 24 May 11:32
a7d600f

Changed

Changed final image to chainguard/wolfi-base

Fixed

Used UUID v7 instead of ULID for request id