Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Spec configuration

Barbacane extends OpenAPI and AsyncAPI specs with custom x-barbacane-* extensions. These tell the gateway how to route requests, apply middleware, and connect to backends.

Extension Overview

ExtensionLocationPurpose
x-barbacane-dispatchOperationRoute request to a dispatcher (required)
x-barbacane-middlewaresRoot or OperationApply middleware chain

Path Parameters

Regular Parameters

Use {paramName} for single-segment parameters — the parameter captures exactly one path segment:

paths:
  /users/{id}/orders/{orderId}:
    get:
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: orderId
          in: path
          required: true
          schema:
            type: string

Wildcard Parameters

Use {paramName+} to capture all remaining path segments as a single value, including any / characters:

paths:
  /files/{bucket}/{key+}:
    get:
      parameters:
        - name: bucket
          in: path
          required: true
          schema:
            type: string
        - name: key
          in: path
          required: true
          allowReserved: true   # tells client tooling not to percent-encode '/'
          schema:
            type: string

A GET /files/my-bucket/docs/2024/report.pdf request captures bucket=my-bucket and key=docs/2024/report.pdf.

Rules:

  • The wildcard parameter must be the last segment of the path
  • At most one wildcard parameter per path
  • Parameter names use the same characters as regular params (alphanumeric and _)

allowReserved note: This is advisory metadata for client generators and documentation tools — it signals that the value may contain unencoded / characters. Barbacane does not parse or enforce it, but including it produces correct client SDKs.


Project Manifest (barbacane.yaml)

The manifest declares the specs folder and plugins available to the gateway:

specs: ./specs/

plugins:
  mock:
    path: ./plugins/mock.wasm
  http-upstream:
    path: ./plugins/http-upstream.wasm
  jwt-auth:
    url: https://github.com/barbacane-dev/barbacane/releases/download/v0.7.0/jwt-auth.wasm
    sha256: abc123...

specs (optional)

Path to a folder containing spec files (relative to the manifest). All *.yaml, *.yml, and *.json files in this folder are discovered as specs.

Used by:

  • barbacane dev — auto-discovers specs for compilation and file watching
  • barbacane compile — falls back to this folder when --spec is not provided

Drop-in spec fragments. Multi-file discovery means you can ship operator-facing fragments alongside the gateway and pull them in with a copy. The repository’s schemas/ai-gateway.yaml is the canonical example — copy it into specs/ to bring up the full OpenAI-compatible AI gateway (/v1/chat/completions, /v1/responses, /v1/models) with one ai-proxy config shared via a YAML anchor. See AI Gateway for the walkthrough.

plugins (required)

Declares all WASM plugins used by your specs. Each plugin maps a name to a source:

  • Local path: path: ./plugins/name.wasm — relative to the manifest directory
  • Remote URL: url: https://... — downloaded at compile time, cached in ~/.barbacane/cache/plugins/
  • Checksum (optional): sha256: ... — integrity verification for remote plugins

Dispatchers

Every operation needs an x-barbacane-dispatch to tell Barbacane how to handle it:

paths:
  /users:
    get:
      x-barbacane-dispatch:
        name: http-upstream
        config:
          url: "https://api.example.com"
          path: /api/v2/users

Dispatch Properties

PropertyTypeRequiredDescription
namestringYesDispatcher plugin name
configobjectNoPlugin-specific configuration

Built-in dispatchers: mock, http-upstream, lambda, kafka, nats, s3. See Dispatchers for configuration details.

Config values support secret references: env://VAR_NAME (environment variable) or file:///path/to/secret (file). See Secrets.


Middlewares

Middlewares process requests before dispatching and responses after.

Global Middlewares

Apply to all operations:

openapi: "3.1.0"
info:
  title: My API
  version: "1.0.0"

x-barbacane-middlewares:
  - name: rate-limit
    config:
      quota: 100
      window: 60
  - name: cors
    config:
      allowed_origins: ["https://app.example.com"]

paths:
  # ... all operations get these middlewares

Operation Middlewares

Apply to a specific operation (runs after global middlewares):

paths:
  /admin/users:
    get:
      security:
        - bearerAuth: []
      x-barbacane-middlewares:
        - name: oidc-auth
          config:
            issuer_url: "https://auth.example.com"
            audience: "my-api"
            required_scopes: "admin:read"
      x-barbacane-dispatch:
        name: http-upstream
        config:
          url: "https://api.example.com"

An operation that runs an authentication middleware needs a security requirement naming a scheme from components.securitySchemes; without one the compiler stops with E1057. The complete example below declares bearerAuth.

Middleware Merging

Operation middlewares are merged with global ones. If an operation middleware has the same name as a global one, the operation config overrides it. Non-overridden globals are preserved.

# Global: rate limit 100/min + cors
x-barbacane-middlewares:
  - name: rate-limit
    config:
      quota: 100
      window: 60
  - name: cors
    config:
      allow_origin: "*"

paths:
  /public/stats:
    get:
      # Override rate-limit; cors still applies from globals
      x-barbacane-middlewares:
        - name: rate-limit
          config:
            quota: 1000
            window: 60
      # Resolved chain: cors (global) → rate-limit (operation override)

Use an empty array to explicitly disable all middlewares for an operation:

x-barbacane-middlewares: []  # No middlewares at all

Middleware Chain Order

  1. Global middlewares (in order defined)
  2. Operation middlewares (in order defined)
  3. Dispatch
  4. Response middlewares (reverse order)

Complete Example

openapi: "3.1.0"
info:
  title: E-Commerce API
  version: "2.0.0"

# Global middlewares
x-barbacane-middlewares:
  - name: correlation-id
    config:
      header_name: X-Request-ID
  - name: cors
    config:
      allowed_origins: ["https://shop.example.com"]
  - name: rate-limit
    config:
      quota: 200
      window: 60

paths:
  /health:
    get:
      operationId: healthCheck
      x-barbacane-dispatch:
        name: mock
        config:
          status: 200
          body: '{"status":"healthy"}'
      responses:
        "200":
          description: OK

  /products:
    get:
      operationId: listProducts
      x-barbacane-middlewares:
        - name: cache
          config:
            ttl: 300
      x-barbacane-dispatch:
        name: http-upstream
        config:
          url: "https://api.shop.example.com"
          path: /api/products
      responses:
        "200":
          description: Product list

  /orders:
    post:
      operationId: createOrder
      security:
        - bearerAuth: []
      x-barbacane-middlewares:
        - name: oidc-auth
          config:
            issuer_url: "https://auth.shop.example.com"
            audience: "shop-api"
      x-barbacane-dispatch:
        name: http-upstream
        config:
          url: "https://api.shop.example.com"
          path: /api/orders
      responses:
        "201":
          description: Order created

  /orders/{orderId}/pay:
    post:
      operationId: payOrder
      security:
        - bearerAuth: []
      x-barbacane-middlewares:
        - name: oidc-auth
          config:
            issuer_url: "https://auth.shop.example.com"
            audience: "shop-api"
            required_scopes: "orders:pay"
      x-barbacane-dispatch:
        name: http-upstream
        config:
          url: "https://payments.example.com"  # Different backend!
          path: /process/{orderId}
          timeout: 45.0
      responses:
        "200":
          description: Payment processed

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

AsyncAPI Support

Barbacane supports AsyncAPI 3.x for event-driven APIs. AsyncAPI specs work similarly to OpenAPI, with channels and operations instead of paths and methods.

Sync-to-Async Bridge Pattern

AsyncAPI send operations are accessible via HTTP POST requests. This enables clients to publish messages to Kafka or NATS through the gateway:

  1. Client sends HTTP POST to the channel address
  2. Gateway validates the message against the schema
  3. Dispatcher publishes to Kafka/NATS
  4. Gateway returns 202 Accepted

Basic AsyncAPI Example

asyncapi: "3.0.0"
info:
  title: User Events API
  version: "1.0.0"

channels:
  userEvents:
    address: /events/users
    messages:
      UserCreated:
        contentType: application/json
        payload:
          type: object
          required:
            - userId
            - email
          properties:
            userId:
              type: string
              format: uuid
            email:
              type: string
              format: email

operations:
  publishUserCreated:
    action: send
    channel:
      $ref: '#/channels/userEvents'
    x-barbacane-dispatch:
      name: kafka
      config:
        brokers: "kafka.internal:9092"
        topic: "user-events"

Channel Parameters

AsyncAPI channels can have parameters (like path params in OpenAPI):

channels:
  orderEvents:
    address: /events/orders/{orderId}
    parameters:
      orderId:
        schema:
          type: string
          format: uuid
    messages:
      OrderPlaced:
        payload:
          type: object

Message Validation

Message payloads are validated against the schema before dispatch. Invalid messages receive a 400 response with validation details.

HTTP Method Mapping

AsyncAPI ActionHTTP Method
sendPOST
receiveGET

Middlewares

AsyncAPI operations support the same middleware extensions as OpenAPI:

operations:
  publishEvent:
    action: send
    channel:
      $ref: '#/channels/events'
    # Authenticated through the security scheme the server declares.
    x-barbacane-middlewares:
      - name: oidc-auth
        config:
          issuer_url: "https://auth.example.com"
          audience: "events-api"
    x-barbacane-dispatch:
      name: kafka
      config:
        brokers: "kafka.internal:9092"
        topic: "events"

API Lifecycle

Barbacane supports API lifecycle management through standard OpenAPI deprecation and the x-sunset extension.

Marking Operations as Deprecated

Use the standard OpenAPI deprecated field:

paths:
  /v1/users:
    get:
      deprecated: true
      summary: List users (deprecated, use /v2/users)
      x-barbacane-dispatch:
        name: http-upstream
        config:
          url: "https://api.example.com"

When a client calls a deprecated endpoint, the response includes a Deprecation: true header per draft-ietf-httpapi-deprecation-header.

Setting a Sunset Date

Use x-sunset to specify when an endpoint will be removed (per RFC 8594):

paths:
  /v1/users:
    get:
      deprecated: true
      x-sunset: "Sat, 31 Dec 2025 23:59:59 GMT"
      x-barbacane-dispatch:
        name: http-upstream
        config:
          url: "https://api.example.com"

The sunset date must be in HTTP-date format (RFC 9110). When set, the response includes a Sunset header per RFC 8594.

Example Response Headers

HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Dec 2025 23:59:59 GMT
Content-Type: application/json

Best Practices

  1. Mark deprecated first: Set deprecated: true before setting a sunset date
  2. Give advance notice: Set the sunset date at least 6 months in advance
  3. Update API docs: Include migration instructions in the operation summary or description
  4. Monitor usage: Track calls to deprecated endpoints via metrics

Validation

The compiler validates your spec:

barbacane validate --spec api.yaml

Errors you might see:

Error CodeMeaning
E1010Routing conflict (same path+method in multiple specs)
E1020Missing x-barbacane-dispatch on operation
E1031Plaintext http:// upstream URL (use HTTPS or --allow-plaintext at compile time)
E1054Invalid path template (unbalanced braces, empty param name, duplicate param, {param+} not last segment, multiple wildcards)

Next Steps