Skip to main content

Built-in Plugins & Middlewares

Aastro ships with a set of ready-to-use plugins and middlewares. They are available without any additional installation - set source: builtin in the flow configuration.

Plugins​

Plugins operate on the JSON response body after it is built - aggregated for a multi-upstream flow, proxied as-is for a single-upstream one. All three built-in plugins run in the response phase, so they don't run at all for a streaming: true flow.

camelify​

Transforms all JSON field names in the response body to camelCase.

plugins:
- name: camelify
source: builtin

No configuration parameters.

Example:

// Before
{ "user_id": 1, "first_name": "Alice", "last_login_at": "2026-01-01" }

// After
{ "userId": 1, "firstName": "Alice", "lastLoginAt": "2026-01-01" }

Transformation is applied recursively to nested objects and arrays. If the response body is not valid JSON, the body is passed through unchanged without error.

snakeify​

Transforms all JSON field names in the response body to snake_case.

plugins:
- name: snakeify
source: builtin

No configuration parameters.

Example:

// Before
{ "userId": 1, "firstName": "Alice", "lastLoginAt": "2026-01-01" }

// After
{ "user_id": 1, "first_name": "Alice", "last_login_at": "2026-01-01" }

Transformation is applied recursively to nested objects and arrays. If the response body is not valid JSON, the body is passed through unchanged without error.

masker​

Replaces the values of specified fields with *** in the JSON response body.

plugins:
- name: masker
source: builtin
config:
fields:
- password
- token
- credit_card
ParameterTypeDescription
fieldslist[string]Field names whose values will be replaced with ***

Example:

// Before
{ "email": "alice@example.com", "token": "secret123", "name": "Alice" }

// After
{ "email": "alice@example.com", "token": "***", "name": "Alice" }

Masking is applied recursively - if a specified field appears at any nesting level, it is masked. Field matching is case-sensitive and exact. If fields is empty or not configured, the plugin is a no-op.

Middlewares​

Middlewares wrap the entire flow handler and run for every request. They execute in the order defined in configuration - the first middleware listed is the outermost wrapper.

recoverer​

Catches panics in downstream handlers and returns a 500 Internal Server Error instead of crashing the process.

middlewares:
- name: recoverer
source: builtin
config:
enabled: true
include_stack: false
ParameterTypeDefaultDescription
enabledboolfalseEnable the middleware
include_stackboolfalseInclude the goroutine stack trace in the error log
warning

Place recoverer first in the middleware list so it wraps all other middlewares and handlers.

logger​

Logs each request with method, path, status code, duration, and request ID.

middlewares:
- name: logger
source: builtin
config:
enabled: true
log_body: false
ParameterTypeDefaultDescription
enabledbooltrueEnable the middleware
log_bodyboolfalseLog the request body. Body is read into memory and replayed - do not enable for large payloads

Log output uses structured JSON fields: method, path, status, duration, request_id, and optionally body.

compressor​

Compresses the response body using gzip or deflate when the client signals support via Accept-Encoding.

middlewares:
- name: compressor
source: builtin
config:
enabled: true
alg: gzip
ParameterTypeDefaultDescription
enabledboolfalseEnable the middleware
algstringgzipCompression algorithm: gzip or deflate

The middleware checks the incoming Accept-Encoding header. If the header does not include the configured algorithm, the response is passed through uncompressed. Content-Length is removed from the response since the compressed body length is unknown in advance.

cors​

Handles Cross-Origin Resource Sharing (CORS) headers and preflight requests.

middlewares:
- name: cors
source: builtin
config:
allowed_origins:
- "https://app.example.com"
- "https://admin.example.com"
allowed_methods:
- GET
- POST
allowed_headers:
- Authorization
- Content-Type
allow_credentials: false
max_age: 3600
ParameterTypeDefaultDescription
allowed_originslist[string][]Allowed origins. Use "*" to allow all origins
allowed_methodslist[string][]Allowed HTTP methods for CORS requests
allowed_headerslist[string][]Allowed headers for CORS requests
allow_credentialsboolfalseSet Access-Control-Allow-Credentials: true
max_ageint0Preflight cache duration in seconds (Access-Control-Max-Age)

Preflight requests (OPTIONS with Origin and Access-Control-Request-Method headers) are handled automatically and return 204 No Content. Requests from disallowed origins receive 403 Forbidden.

warning

allow_credentials: true cannot be combined with allowed_origins: ["*"]. Using wildcard origins with credentials is rejected at initialization.

auth​

Validates JWT tokens from the Authorization: Bearer <token> header. Supports three key sources: HMAC shared secret, static RSA public key, and JWKS endpoint.

HS256 - HMAC shared secret:

middlewares:
- name: auth
source: builtin
config:
alg: HS256
issuer: "https://auth.example.com"
audience: "api"
hmac_secret: "dGhpcyBpcyBhIHNlY3JldA=="

The hmac_secret value must be base64-encoded.

RS256 - static RSA public key:

middlewares:
- name: auth
source: builtin
config:
alg: RS256
issuer: "https://auth.example.com"
audience: "api"
rsa_public_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----

RS256 - JWKS endpoint:

middlewares:
- name: auth
source: builtin
config:
alg: RS256
issuer: "https://auth.example.com"
audience: "api"
jwks_url: "https://auth.example.com/.well-known/jwks.json"
jwks_refresh_timeout: "5s"
jwks_refresh_interval: "5m"
ParameterTypeDefaultDescription
algstring-Signing algorithm: HS256 or RS256
issuerstring-Expected iss claim value
audiencestring-Expected aud claim value
hmac_secretstring-Base64-encoded HMAC secret. Required for HS256
rsa_public_keystring-PEM-encoded RSA public key. Used for static RS256
jwks_urlstring-URL of the JWKS endpoint. Takes priority over rsa_public_key for RS256
jwks_refresh_timeoutduration5sHTTP timeout for each JWKS fetch request
jwks_refresh_intervalduration5mHow often the JWKS cache is refreshed in the background

Validation: the middleware verifies the signature, expiry (exp), not-before (nbf), issuer (iss), and audience (aud) claims. A 5-second leeway is applied to exp and nbf to tolerate minor clock skew.

JWKS caching: on startup, the middleware performs a blocking fetch of the JWKS endpoint. If the fetch fails, initialization fails and the gateway does not start. After that, keys are refreshed in the background every jwks_refresh_interval. On a cache miss during request handling (unknown kid), an immediate on-demand refresh is triggered before rejecting the token.

Unauthorized response: all validation failures return 401 Unauthorized with no detail about the specific failure reason.