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
| Extension | Location | Purpose |
|---|---|---|
x-barbacane-upstream | Server object | Define named backend connections |
x-barbacane-dispatch | Operation | Route request to a dispatcher |
x-barbacane-middlewares | Root or Operation | Apply middleware chain |
Upstreams
Define backend connections on the servers array:
servers:
- url: https://api.example.com
description: Production API
x-barbacane-upstream:
name: main-backend
timeout: 30s
retries: 3
- url: https://auth.example.com
description: Auth Service
x-barbacane-upstream:
name: auth-service
timeout: 10s
Upstream Properties
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique identifier for this upstream |
timeout | duration | No | Request timeout (default: 30s) |
retries | integer | No | Number of retry attempts (default: 0) |
Upstreams are a design pattern for named backends. The http-upstream dispatcher uses the url config directly:
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com" # Direct URL to backend
path: /api/resource
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
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Dispatcher plugin name |
config | object | No | Plugin-specific configuration |
Built-in Dispatchers
mock - Return Static Responses
For health checks, stubs, or testing:
x-barbacane-dispatch:
name: mock
config:
status: 200
body: '{"status":"ok","version":"1.0"}'
| Config | Type | Default | Description |
|---|---|---|---|
status | integer | 200 | HTTP status code |
body | string | “” | Response body |
http-upstream - Proxy to HTTP Backend
Forward requests to an upstream:
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
path: /api/users/{id}
timeout: 10.0
| Config | Type | Default | Description |
|---|---|---|---|
url | string | Required | Base URL of upstream (HTTPS required in production) |
path | string | Same as operation | Backend path (supports {param} substitution) |
timeout | number | 30.0 | Request timeout in seconds |
Path parameters from the OpenAPI spec are substituted automatically:
# OpenAPI path: /users/{userId}/orders/{orderId}
# Request: GET /users/123/orders/456
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
path: /api/v2/users/{userId}/orders/{orderId}
# Becomes: GET https://api.example.com/api/v2/users/123/orders/456
Secret References in Config
Config values can reference secrets instead of hardcoding sensitive data:
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
headers:
Authorization: "Bearer env://UPSTREAM_API_KEY"
Supported formats:
env://VAR_NAME- Read from environment variablefile:///path/to/secret- Read from file
Secrets are resolved at gateway startup. If any secret is missing, the gateway fails with exit code 13. See Secrets for details.
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:
requests_per_minute: 100
- 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:
x-barbacane-middlewares:
- name: auth-jwt
config:
required: true
scopes: ["admin:read"]
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
Middleware Override
Operation middlewares can override global ones by name:
# Global: rate limit 100/min
x-barbacane-middlewares:
- name: rate-limit
config:
requests_per_minute: 100
paths:
/public/stats:
get:
# Override: higher limit for this endpoint
x-barbacane-middlewares:
- name: rate-limit
config:
requests_per_minute: 1000
Middleware Chain Order
- Global middlewares (in order defined)
- Operation middlewares (in order defined)
- Dispatch
- Response middlewares (reverse order)
Complete Example
openapi: "3.1.0"
info:
title: E-Commerce API
version: "2.0.0"
servers:
- url: https://api.shop.example.com
x-barbacane-upstream:
name: shop-backend
timeout: 30s
retries: 2
- url: https://payments.example.com
x-barbacane-upstream:
name: payments
timeout: 60s
# Global middlewares
x-barbacane-middlewares:
- name: request-id
config:
header: X-Request-ID
- name: cors
config:
allowed_origins: ["https://shop.example.com"]
- name: rate-limit
config:
requests_per_minute: 200
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
x-barbacane-middlewares:
- name: auth-jwt
config:
required: true
- name: idempotency
config:
header: Idempotency-Key
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
x-barbacane-middlewares:
- name: auth-jwt
config:
required: true
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
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:
- Client sends HTTP POST to the channel address
- Gateway validates the message against the schema
- Dispatcher publishes to Kafka/NATS
- 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:
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 Action | HTTP Method |
|---|---|
send | POST |
receive | GET |
Middlewares
AsyncAPI operations support the same middleware extensions as OpenAPI:
operations:
publishEvent:
action: send
channel:
$ref: '#/channels/events'
x-barbacane-middlewares:
- name: jwt-auth
config:
required: true
x-barbacane-dispatch:
name: kafka
config:
topic: "events"
API Lifecycle
Barbacane supports API lifecycle management through standard OpenAPI deprecation and the x-barbacane-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-barbacane-sunset to specify when an endpoint will be removed:
paths:
/v1/users:
get:
deprecated: true
x-barbacane-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
- Mark deprecated first: Set
deprecated: truebefore setting a sunset date - Give advance notice: Set the sunset date at least 6 months in advance
- Update API docs: Include migration instructions in the operation summary or description
- 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 Code | Meaning |
|---|---|
| E1010 | Routing conflict (same path+method in multiple specs) |
| E1020 | Missing x-barbacane-dispatch on operation |
| E1031 | Plaintext http:// upstream URL (use HTTPS or --allow-plaintext-upstream) |
Next Steps
- Dispatchers - All dispatcher types and options
- Middlewares - Available middleware plugins
- CLI Reference - Full command options