Skip to content

feat(plugin): error-page: support 403 and Nginx variables in body #13742

Description

@baiuu

Description

Description

The error-page plugin currently has two limitations that make custom error pages less useful in production:

1. Limited status code coverage. Only 404/500/502/503 are supported. APISIX-generated 403 responses are common — auth plugin rejections (key-auth, jwt-auth, etc.), ACL blocks, or custom serverless logic — but they cannot be replaced with a custom page.

2. Static body only. The configured body is returned as a static string. Operators typically want to embed request-scoped information into error pages — most importantly the request ID, so that end users can report it and administrators can correlate the error page with access/error logs.

Proposal

Part 1 — Support 403:

  • Add error_403 to metadata_schema (same structure as existing entries)
  • Lower the status threshold in get_metadata from status < 404 to status < 400; interception still requires an explicitly configured error_<status> key, so behavior for unconfigured codes is unchanged

Part 2 — Nginx variables in body:

  • Resolve variables via core.utils.resolve_var (the same mechanism used by response-rewrite headers) before sending the response
  • Resolution happens in header_filter so Content-Length is computed from the final rendered body (avoids truncation/connection stalls)
  • Supports $var, ${var}, the ?? default-value operator, and \$ escaping
  • Fail-open: on resolution failure, fall back to the original body and log a warning
  • Zero overhead for existing configurations (bodies without $ short-circuit before regex processing)

Example:

{
    "enable": true,
    "error_403": {
        "body": "<html><body><h1>403 Forbidden</h1><p>Request ID: $apisix_request_id</p></body></html>",
        "content_type": "text/html"
    }
}

Both parts are backward compatible and independent of each other, but they combine naturally — e.g. a custom 403 page showing $apisix_request_id for troubleshooting auth rejections.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status
    📋 Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions