Bondy Connect
Skip to content

HTTP API Gateway Specification ​

An API Gateway specification is a document that tells Bondy how to route incoming HTTP requests to your WAMP APIs or to external HTTP/REST APIs.

Overview ​

An API Gateway Specification document is a JSON data structure that declaratively defines an HTTP/REST API and how Bondy should handle each HTTP Request e.g. by converting it into a WAMP operation or forwarding it to an upstream (external) HTTP/REST API. This includes capabilities for data transformation.

A declarative Finite State Machine (FSM)

In effect, an API Gateway Specification is a declarative definition of an API Gateway Finite State Machine that exposes an HTTP/REST API and converts its nouns and verbs to either WAMP or other HTTP/REST actions.

With this approach you can create a whole HTTP/REST API from scratch without any coding.

The API Gateway Specification document has a structure represented by the following object tree:

The following diagram shows the object tree in detail, including all properties and types.

The properties of the objects in the object tree can contain static values and/or dynamically evaluated values via expressions that are resolved against the HTTP request data at runtime.

FSM State

The API Context is the state of the API Gateway FSM. It is incrementally and recursively constructed.

So an API Gateway Specification is the basis of an API Context but also it is evaluated against it, primarily because the context will contain the Request Object at runtime.

The key to the definition of an API Gateway Specification is understanting the API Context, since defining a specification implies writing expressions that target (read and/or update) the context.

On the Open API standard

Open API (formerly Swagger) defines a standard on how HTTP APIs are described, not its implementation. An API Gateway Specification describes an API and the behaviour of the Gateway, that is, it also defines its implementation in terms of the actions that the Gateway performs.

API Context ​

The API context is a map data structure created by the API Gateway. At runtime, it contains the HTTP Request data as well as the results of parsing and evaluating the definitions and expressions defined in an API Gateway Specification.

The context contains the following keys:

requestRequestObject

The contents (data and metadata) of the HTTP request being evaluated. The request data is available at runtime, so any expression defined during design time will result in a promise that will be evaluated to a value when handling the HTTP request.

securitymap

The identity of the authenticated caller. The gateway sets it at runtime, after it authenticates the request with an OAuth2 token, so an expression that reads it is a promise. It holds realm_uri, session, client_id, authid, username (same value as authid), authmethod, groups, locale and meta. The authentication scheme itself is set by the Security Object, not by this key.

actionobject

At runtime, it will contain the result or error of the action performed by the API Gateway during the handling of an HTTP request.

variablesmap

A mapping of arbitrary variable names to values or expressions. Each entry in this map is obtained during the parsing of the API Object tree. At each level of the tree this property will merge in the values of the target object's variables property, so children nodes can access the entries defined in the ancestors, override them and/or add new variables to the context.

defaultsmap

A mapping of object properties to their default values. Each entry in this map is obtained during the parsing of the API Object tree. At each level of the tree this property will merge in the values of the target object's defaults property, so children nodes can access the entries defined in the ancestors, override them and/or add new defaults to the context. Expressions in the defaults mapping can reference variables in the variables property.

status_codesmap

A mapping of error URIs to HTTP status codes. Bondy initialises it from the default HTTP status of each URI in the error catalogue. The API Object status_codes entries override it, and so do the Version Object entries for that version's paths. Only an expression that reads this map uses it; see Status Codes.

Default: The error catalogue defaults.

Request Object ​

The object represents the contents (data and metadata) of an HTTP request. At runtime, the API Gateway writes this object in the API Context request property.

idstringIMMUTABLE

A unique tracing identifier for the request, in W3C trace-id form: 32 hexadecimal characters.

methodstringIMMUTABLE

The HTTP method of the request. One of the following values:

  • delete
  • get
  • head
  • options
  • patch
  • post
  • put
schemearray[string]IMMUTABLE

An array of strings where values can be: http or https.

Default: ["http"]
peernamestringIMMUTABLE

A string representation of the requester IP address and port number e.g. 127.0.0.1:54678.

pathstringIMMUTABLE

The relative path of the request.

hoststringIMMUTABLE

The hostname of the request.

portintegerIMMUTABLE

The port number of the request.

headers() => mapIMMUTABLE

A mapping of HTTP headers to their corresponding values.

languagestringIMMUTABLE

The requested language.

Default: "en"
query_stringstringIMMUTABLE

The HTTP query string. See query_params.

query_paramsmapIMMUTABLE

A map of query params to values. This is the result of parsing the request's query_string.

Examples:

Request Property Value
GET /users?region=us&type=individual {"region": "us", "type": "individual"}
GET /users?x=100&y=200 {"x": "100", "y": "200"}
bindingsmapIMMUTABLE

A map of path variable bindings. Bindings occur when the Path Object contains patterns.

Examples: For the path specification /accounts/:acc_id/users/:user_id

Request Property Value
GET /accounts/001/users/002 {"acc_id": "001", "user_id": "002"}
bodyanyIMMUTABLE

The body of the request. This is the result of decoding the HTTP body using the encoding determined by the Path Object accepts property which defines the content-types allowed for POST, PUT and PATCH.

body_lengthintegerIMMUTABLE

The length of the body in bytes.

You access the values in this object by writing expressions using the API Specification expression language.

Result Object ​

WAMP Result ​

The result for a WAMP Action.

This object will be accessible with the expression {{action.result}}.

request_idintegerIMMUTABLE

The WAMP RESULT.id.

detailsmapIMMUTABLE

The WAMP RESULT.details.

argsarray[any]IMMUTABLE

The WAMP RESULT.args.

kwargs() => mapIMMUTABLE

The WAMP RESULT.kwargs.

HTTP Forward Result ​

The result of a Forward Action whose upstream responded with a status code below 400.

This object will be accessible with the expression {{action.result}}.

json
{
    "status_code": 200,
    "headers": { "content-type": "application/json" },
    "body": "...",
    "uri": ""
}

uri is the upstream response's Location header, if it sent one, or an empty string otherwise.

Error Object ​

The shape of {{action.error}} when an action fails, for either a WAMP Action or a Forward Action.

For a WAMP action, the error is the called procedure's own WAMP ERROR message, with an added status_code. Bondy derives status_code from error_uri through the default HTTP status of the error catalogue, not through the specification's status_codes map:

json
{
    "error_uri": "com.example.error.not_found",
    "args": ["The requested resource was not found."],
    "kwargs": {},
    "details": {},
    "status_code": 404
}

For a Forward Action whose upstream responded with a status code of 400 or above, the error is the raw upstream response:

json
{
    "status_code": 404,
    "headers": { "content-type": "application/json" },
    "body": "..."
}

Expression Language ​

Most API Specification object properties support expressions using an embedded logic-less domain-specific language (internally called "Mops") for data transformation and dynamic configuration.

This same language is also used by the Broker Bridge Specification.

The expression language operates on the API Context and it works by expanding keys (or key paths) provided in a context object and adding or updating keys in the same context object.

Let's assume that we receive the following HTTP request:

bash
curl -X "POST" "http://localhost:18080/accounts/" \
-H 'Content-Type: application/json; charset=utf-8' \
-H 'Accept: application/json; charset=utf-8' \
--data-binary '{
    "id" : 12345
    "sku" : "ZPK1972",
    "price" : 13.99,
    "customer": {
        "first_name": "John",
        "last_name": "Doe",
        "email" : "john.doe@foo.com"
    },
    "ship_to": {
        "first_name": "May",
        "last_name": "Poppins",
        "address" : "3 High Street",
        "town" : "Guildford",
        "county" : "Surrey",
        "zip"   : "GU1 1AF"
    },
    "bill_to": {
        "first_name": "John",
        "last_name": "Doe",
        "address" : "13 Sandy Lane",
        "town" : "Esher",
        "county" : "Surrey",
        "zip"   : "KT11 2PQ"
    }
}'

Let's explore a some example to demonstrate how you can use expression in Bondy's configuration objects to read data from the HTTP Request.

The following table shows some example expressions being evaluated against the API Context for the above HTTP Request.

Expression StringEvaluates To
{{request.method}}POST
{{request.body}}{"id": 12345, "bill_to":...}
{{request.body.sku}}"ZPK1972"
"The sku number is {{request.body.sku}}""The sku number is ZPK1972"
{{request.body.price}}13.99
{{request.body.price |> integer}}13
{{request.body.customer.first_name}}"John"
"{{request.body.customer.first_name}} {{request.body.customer.last_name}}""John Doe"
{{variables.foo}}Returns the value of the foo variable
{{status_codes}}Returns the status codes map

Learn more

Expressions also allow to set values in the context and use functions to manipulate the request data. Learn more about expressions in the API Specification Expressions reference section.

Specification Evaluation ​

Incremental Evaluation ​

The API Specification evaluation performed incrementally in two stages:

  1. During loading, validation and parsing. All API Specification expressions will be evaluated to either a (final) value or a promise. Promises occur when an expression depends directly or indirectly (transitive closure) on HTTP request data. This results in a context object.
  2. During HTTP request handling at runtime. The context created in the first stage is updated with the HTTP request data and the API Specification is evaluated again using the updated context, yielding the actions to be performed with all promises evaluated to values (grounded).

Recursive Evaluation ​

The evaluation of the expressions in the API Gateway Specification is done by passing the API Context recursively throughout the specification object tree.

At each level of the tree children nodes can can use the values of the certain properties defined in the ancestor node (through expressions), override them and/or update the API Context.

Validation ​

Each object accepts only the properties listed for it on this page, under any of their names. The parser refuses a specification that has any other key in one of these places:

  • the API, Version, Path and Operation objects;
  • an Action Object, according to its type;
  • the on_result and on_error objects of a Response Object;
  • the defaults of the API, a version or a path;
  • a Security Object, according to its type.

A misspelt key is therefore refused, not replaced by its default. The info object of a version or an operation is the exception: it is free-form, and the parser checks only that it is an object.

API Object ​

The API object is the root of an API Specification. It contains one or more API Version objects.

idstringREQUIREDIMMUTABLE

A global unique identifier for this API.

hoststringREQUIREDIMMUTABLE

A string used for matching the incoming HTTP request HOST header value. Hosts with and without a trailing dot are equivalent for routing. Similarly, hosts with and without a leading dot are also equivalent e.g. cowboy.example.org, cowboy.example.org. and .cowboy.example.org are equivalent. A pattern using the keyword : and wildcard _ can be used to match multiple domains e.g. mydomain.:_ will match mydomain.foo and mydomain.bar but not mydomain.foo.baz. Bondy serves the specification's paths only to requests whose host matches. See Request matching.

realm_uristringREQUIREDIMMUTABLE

The realm this API will target. An API can only target a single realm.

namestringIMMUTABLE

A display name for the API.

metamapIMMUTABLE

A mapping of metadata keys to values.

variablesmapIMMUTABLE

A mapping of arbitrary variable names to values or expressions. This variables can be referenced by expressions in the children objects of this object.

defaultsmapIMMUTABLE

A mapping of attributes to their default values. This values are inherited by children objects as defaults when their value is unset.

status_codesmapIMMUTABLE

A mapping of WAMP Error URIs to HTTP Status Codes. This values are inherited by children objects as defaults when their value is unset.

Default: Check the default values below.
versionsmapREQUIREDIMMUTABLE

A mapping of version names to Version Object instances.

API Object example
json
{
  "id": "example-api",
  "name" : "Bonding in HTTP",
  "host" : "_",
  "realm_uri" : "com.example.public",
  "meta": {"foo" : "bar"},
  "variables" : {
     "cors_headers": {
        "access-control-allow-origin": "*",
        "access-control-allow-credentials": "true",
        "access-control-allow-methods": "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
        "access-control-allow-headers": "origin,x-requested-with,content-type,accept,authorization,accept-language",
        "access-control-max-age": "86400"
    }
  },
  "defaults" : {
    "schemes" : ["http"]
  },
  "status_codes": {
    "com.example.error.not_found": 404,
    "com.example.error.unknown_error": 500,
    "com.example.error.internal_error": 500
  },
  "versions" : {
    ...
  }
}

Request matching ​

Bondy serves the paths of a specification only to requests whose host matches the specification's host.

When more than one host, or more than one path, matches a request, the most specific one answers it. At the first segment where two hosts or two paths differ in kind, a literal segment wins over a binding such as :id, and a binding wins over [...]. The host or path _ comes last. Bondy compares hosts from the top-level domain.

Bondy's own paths, such as /ping and /metrics, belong to the host _. When a specification declares one of these paths, the outcome depends on the specification's host:

  • With the host _, Bondy's own path answers the request.
  • With any other host, the specification's path answers requests for that host.

When two specifications declare the same path for the same host, only one of them answers it. In each of these cases Bondy logs a warning and serves the other paths of the specification.

Bondy serves a specification's paths only while its realm exists. When the realm is deleted, its specifications stay stored and their paths stop being served. After the realm is created again, the next rebuild of the routes on a node serves them again on that node. Loading or deleting any specification triggers a rebuild.

Version Object ​

The Version Object represents a particular API version.

base_pathstringREQUIREDIMMUTABLE

The base path for this version of the API. This value will be used by the API Gateway to match incoming requests e.g. /v1.0 will match /v1.0/foo but not /foo. It is possible to have optional segments, anything between brackets is optional e.g. /[v1.0] will match /v1.0/foo and also /foo.

pathsmapREQUIREDIMMUTABLE

A mapping of paths to Path Objects. Paths are relative URL paths and can contain patterns and optional segments. The path / is invalid while the path /ws is reserved (used by Bondy for requesting Websocket connections).

is_activebooleanIMMUTABLE

Whether Bondy serves the paths of this version. When false, Bondy adds no route for the version.

Default: true
is_deprecatedbooleanIMMUTABLE

Whether the path is deprecated i.e. the path will be removed in future versions of the API.

Default: false
pool_sizeintegerIMMUTABLE

The parser accepts this key. Bondy does not use its value.

Default: 200
infomapIMMUTABLE

Free-form information about this version, such as a title and a description. The parser checks only that the value is an object, and keeps its keys.

variablesmapIMMUTABLE

A mapping of arbitrary variable names to values or expressions. This variables can be referenced by expressions in the children objects of this object. These values are merged with and thus override the ones inherited from the API Object variables property.

defaultsmapIMMUTABLE

A mapping of attributes to their default values. This values are inherited by children objects as defaults when their value is unset. These values are merged with and thus override the ones inherited from the API Object defaults property.

status_codesmapIMMUTABLE

A mapping of WAMP Error URIs to HTTP Status Codes.

languagesarray[string]IMMUTABLE

An array of language code string.

Default: ["en"]
Version Object example
json
{
    "base_path": "/[v1.0]",
    "is_active": true,
    "is_deprecated": false,
    "languages": ["en"],
    "info": {
        "title": "Marketplace API v1.0",
        "description": "Version 1.0 of the Marketplace demo API."
    },
    "defaults": {
        "timeout": 20000
    },
    "status_codes": {
        "com.example.error.not_found": 404,
        "com.example.error.internal_error": 500
    },
    "paths": {
        "/services/echo": {
            "get": { }
        }
    }
}

Path Object ​

A path specification to be used as a value to a key in the paths property of a Version Object.

summarystringIMMUTABLE

A short summary of the API.

descriptionstringIMMUTABLE

A description of the API.

variablesmapIMMUTABLE

A mapping of arbitrary variable names to values or expressions. This variables can be referenced by expressions in the children objects of this object. These values are merged with and thus override the ones inherited from the API Object variables property.

defaultsmapIMMUTABLE

A mapping of attributes to their default values or a MOPS expression resolving to such a map. This values are inherited by children objects as defaults when their value is unset. These values are merged with and thus override the ones inherited from the API Object default property.

is_collectionbooleanIMMUTABLE

Defines whether the resource managed in this path is a collection or not.

Default: false
acceptsarray[string]IMMUTABLE

An array of content types. The supported content types are:

  • application/json
  • application/json; charset=utf-8
  • application/msgpack
  • application/msgpack; charset=utf-8
  • application/x-www-form-urlencoded
Default: defaults.accepts
providesarray[string]IMMUTABLE

An array of content types. The supported content types are:

  • application/json
  • application/json; charset=utf-8
  • application/msgpack
  • application/msgpack; charset=utf-8
Default: defaults.provides
schemesarray[string]IMMUTABLE

An array of strings where values can be: http or https.

Default: defaults.schemes
securitySecurityObjectIMMUTABLE
Default: defaults.security
deleteOperationObjectIMMUTABLE

The operation specification to perform in case the API Gateway receives an HTTP DELETE Request.

getOperationObjectIMMUTABLE

The operation specification to perform in case the API Gateway receives an HTTP GET Request.

headOperationObjectIMMUTABLE

The operation specification to perform in case the API Gateway receives an HTTP HEAD Request.

optionsOperationObjectIMMUTABLE

The operation specification to perform in case the API Gateway receives an HTTP OPTIONS Request.

patchOperationObjectIMMUTABLE

The operation specification to perform in case the API Gateway receives an HTTP PATCH Request.

postOperationObjectIMMUTABLE

The operation specification to perform in case the API Gateway receives an HTTP POST Request.

putOperationObjectIMMUTABLE

The operation specification to perform in case the API Gateway receives an HTTP PUT Request.

Path Object example
json
{
    "id": "example-api",
    ...,
    "versions" : {
        "base_path": "v1.0",
        ...,
        "paths" : {
            "/path/to/resource" : {
                "get" : {
                    ...
                },
                "post" : {
                    ...
                }
            },
            "/path/to/:resourceId" : {
                "get" : {
                    ...
                },
                "post" : {
                    ...
                }
            },
            "/path/to/other/resource" : {
                "get" : {
                    ...
                },
                "post" : {
                    ...
                }
            }
        }
    }
}

Operation Object ​

actionActionObjectREQUIREDIMMUTABLE
responseResponseObjectREQUIREDIMMUTABLE
infomapIMMUTABLE

Free-form information about this operation. The parser checks only that the value is an object, and keeps its keys.

body_max_bytesintegerIMMUTABLE
Default: defaults.body_max_bytes
body_read_bytesintegerIMMUTABLE
Default: defaults.body_read_bytes
body_read_secondsintegerIMMUTABLE
Default: defaults.body_read_seconds
Operation Object example
json
{
    "info": {"summary": "Echoes the request body back to the caller."},
    "body_max_bytes": 1048576,
    "action": {
        "type": "static",
        "body": "{{request.body}}"
    },
    "response": {
        "on_result": {
            "body": "{{action.result}}"
        }
    }
}

Action Object ​

The API Gateway supports four types of action: static, forward, wamp_call and wamp_publish.

Static Action ​

An action that returns a static response.

typestringREQUIREDIMMUTABLE

The value static.

headers() => mapIMMUTABLE

A mapping of HTTP headers to their corresponding values.

body() => anyIMMUTABLE

The body to be returned with the response.

Static Action example
json
{
    "type": "static",
    "headers": {
        "content-type": "application/json"
    },
    "body": {
        "status": "operational",
        "version": "1.0.0"
    }
}

Forward Action ​

An action that forwards the incoming HTTP request to an upstream HTTP endpoint.

typestringREQUIREDIMMUTABLE

The value forward.

http_methodstringIMMUTABLE

The HTTP method to be used when forwarding the request to the upstream endpoint. The value is one of the HTTP methods below, written as a literal value, not as an expression:

  • delete
  • get
  • head
  • options
  • patch
  • post
  • put
Default: The method of the incoming request.
hoststringREQUIREDIMMUTABLE

The upstream origin, such as https://upstream.example.com or upstream.example.com:8080. Without a scheme, the gateway uses http. The gateway appends path and query_string to it.

path() => stringREQUIREDIMMUTABLE

The upstream path.

query_string() => stringIMMUTABLE

The upstream query string.

headers() => mapIMMUTABLE

A mapping of HTTP headers to their corresponding values.

body() => anyIMMUTABLE

The body to be forwarded to the upstream endpoint.

timeout() => integerIMMUTABLE

The time in milliseconds to wait for the upstream response.

Default: defaults.timeout
connect_timeout() => integerIMMUTABLE

The time in milliseconds to wait for the connection to the upstream.

Default: defaults.connect_timeout
retries() => integerIMMUTABLE

The number of times the gateway sends a request again when the upstream sends no response. Only a request with an idempotent method is sent again. See Retries.

Default: defaults.retries
retry_timeout() => integerIMMUTABLE

The time in milliseconds to wait before each retry, as a non-negative integer.

Default: defaults.retry_timeout
Forward Action Object example
json
{
    "type": "forward",
    "host": "upstream.example.com",
    "path": "{{request.path}}",
    "query_string": "{{request.query_string}}",
    "headers": "{{request.headers}}",
    "body": "{{request.body}}",
    "timeout": 5000,
    "connect_timeout": 5000,
    "retries": 2,
    "retry_timeout": 1000
}

Retries ​

When the upstream sends no response, the gateway sends the request again only if its method is idempotent (RFC 9110, section 9.2.2): get, head, options, put or delete. The gateway sends the request up to retries more times, and waits retry_timeout milliseconds before each retry. A timeout counts as no response. The gateway never sends a post or patch request again. It never retries a request that received a response, whatever its status.

Responses ​

The upstream status becomes the response status unless the Response Object sets status_code.

When the response body is {{action.result.body}} or {{action.error.body}}, the gateway sends the upstream bytes as it received them. The response then keeps the upstream content-type, or has none when the upstream sent none. A content-type in the Response Object headers replaces the upstream one. The gateway sends any other text body as it is. It encodes any other body in the negotiated content type.

Failures without a response ​

When the upstream sends no response and no retry is left, the gateway answers with an error body and does not evaluate on_error:

CauseError URIStatus
The connect or the response outlasts connect_timeout or timeoutbondy.error.gateway_timeout504
Any other failure to reach the upstreambondy.error.bad_gateway502

WAMP Action ​

An action that transforms an incoming HTTP request to a WAMP operation.

typestringREQUIREDIMMUTABLE

The value wamp_call. For wamp_publish, see WAMP Publish Action.

procedure() => stringREQUIREDIMMUTABLE

The URI of the procedure to call.

optionsmapIMMUTABLE

The WAMP message options.

Default: {}
argsarray[() => any]IMMUTABLE

The WAMP message args.

Default: []
kwargs() => mapIMMUTABLE

The WAMP message kwargs.

Default: {}
timeout() => integerIMMUTABLE

The CALL option timeout, in milliseconds, unless options sets a non-zero timeout.

Default: defaults.timeout
retries() => integerIMMUTABLE

The CALL option _retries, unless options sets a non-zero _retries.

Default: defaults.retries

A wamp_call action passes its timeout as the CALL option timeout, and its retries as the CALL option _retries. A non-zero value of the same option in options takes precedence. After a timeout or the loss of the callee, the router retries the call only when the callee registered the procedure with _idempotent set to true. The action accepts no connect_timeout and no retry_timeout.

WAMP Action example
json
{
    ...
    "paths": {
        "/accounts" : {
            "post": {
                "action": {
                    "type": "wamp_call",
                    "procedure": "com.example.account",
                    "options": {"timeout": 15000},
                    "args" : ["{{request.body}}"],
                    "kwargs" : {}
                },
                "response": {,
                    ...
                }
            }
        }
    }
}

WAMP Publish Action ​

An action that publishes an event to a WAMP topic, with type set to wamp_publish. Its fields are those of the WAMP call action, with topic in place of procedure: topic, options, args and kwargs. It also accepts timeout, which defaults to defaults.timeout; the gateway does not pass it to the publication. It accepts no retries. Every field can be an expression evaluated against the API Context.

On success, action.result is {"publication_id": <id>}.

WAMP Publish Action example
json
{
    "type": "wamp_publish",
    "topic": "com.example.account.created",
    "options": {},
    "args": ["{{request.body}}"],
    "kwargs": {},
    "timeout": 15000
}

Response Object ​

The response object defines what the API Gateway should respond in case of a successful result or error. The purpose of this declaration is to be able to customise the outcome of the action performed according to the Action Object declaration.

The outcome is obtained from the API Context action property by using an expression such as {{action.result.PROP}} (in case of a successful result) and {{action.error.PROP}} (in case of an error) where PROP will depend on the type of action performed.

on_resultobjectREQUIRED

A declaration of the desired HTTP response in case the action (as defined in the sibling action object) was successful.

on_errorobjectREQUIRED

A declaration of the desired HTTP response in case the action (as defined in the sibling action object) failed.

WAMP Response Object Example
json
{
    ...
    "paths": {
        "/accounts" : {
            "post": {
                "action": {
                    "type": "wamp_call",
                    ...
                },
                "response": {,
                    "on_result": {
                        "body": "{{action.result.args |> head}}"
                    },
                    "on_error": {
                        "status_code": "{{status_codes |> get({{action.error.error_uri}}, 500) |> integer}}",
                        "body": {
                            "error_uri": "{{action.error.error_uri}}",
                            "args": "{{action.error.args}}",
                            "kwargs": "{{action.error.kwargs}}",
                            "details": "{{action.error.details}}"
                        }
                    }
                }
            }
        }
    }
}

Defaults Object ​

The defaults object is used to define default values for the API specification objects properties.

The API Specification parser will use this object to find a default value for the following keys when evaluating the different objects:

schemesarray[string]IMMUTABLE

An array of strings where values can be: http or https.

Default: ["http"]
acceptsarray[string]IMMUTABLE

An array of content types. The supported content types are:

  • application/json
  • application/json; charset=utf-8
  • application/msgpack
  • application/msgpack; charset=utf-8
  • application/x-www-form-urlencoded
Default: ["application/json", "application/msgpack"]
providesarray[string]IMMUTABLE

An array of content types. The supported content types are:

  • application/json
  • application/json; charset=utf-8
  • application/msgpack
  • application/msgpack; charset=utf-8
Default: ["application/json", "application/msgpack"]
headers() => mapIMMUTABLE

A mapping of HTTP headers to their corresponding values.

Default: {}
securitySecurityObject
Default: {}
body_max_bytesintegerIMMUTABLE
Default: 25000000
body_read_bytesintegerIMMUTABLE
Default: 8000000
body_read_secondsintegerIMMUTABLE
Default: 15000
timeout() => integerIMMUTABLE

The default timeout of a forward, wamp_call or wamp_publish action, in milliseconds.

Default: 60000
connect_timeout() => integerIMMUTABLE

The default connect_timeout of a forward action, in milliseconds.

Default: 8000
retries() => integerIMMUTABLE

The default retries of a forward or wamp_call action.

Default: 0
retry_timeout() => integerIMMUTABLE

The default retry_timeout of a forward action, in milliseconds.

Default: 5000

Security Object ​

The Security Object defines how requests to an API version authenticate. The router enforces three of the schemes the parser accepts:

typeRequests to the version's pathsRoutes Bondy adds under the version's base_path
(empty object)Served without authentication.None.
oauth2Require a valid Bondy OAuth2 access token.The token and revoke paths, /oauth/jwks, and a verify route.
oidcRequire the realm's OIDC ticket cookie, bondy_ticket_<realm_uri>. A request other than GET, HEAD or OPTIONS must also send the value of the bondy_csrf_<realm_uri> cookie in x-csrf-token./oidc/login, /oidc/<provider>/callback, /oidc/logout, and a verify route. See OIDC Authentication.
basicRefused.None.
api_keyRefused.None.

Each scheme accepts only the keys listed for it below. The parser refuses any other key, including scopes: the gateway checks no OAuth2 scope.

basic and api_key do not protect a path

A specification using one of these schemes loads, but Bondy refuses every request to the version's own paths. It never serves them without authentication. Use oauth2 or oidc to protect an HTTP API.

An oidc path authenticates the cookie the way a WAMP session opened with it authenticates: the realm's authmethods must include cookie, the ticket's scope must cover the realm, and its issuer must be trusted by the realm. A ticket issued for an identity Bondy does not store takes its roles from the ticket.

OAuth2 Authentication ​

typestringREQUIREDIMMUTABLE

A value of oauth2.

schemesarray[string]IMMUTABLE

An array of strings where values can be: http or https.

Default: ["http"]
flowstringREQUIREDIMMUTABLE

One of the following values:

  • implicit
  • authorization_code
  • client_credentials
  • resource_owner_password_credentials
token_pathstringIMMUTABLE

The relative path to use for the obtain/refresh token action.

Default: "/oauth/token"
revoke_token_pathstringIMMUTABLE

The relative path to use for the revoke token action.

Default: "/oauth/revoke"
verify_pathstringIMMUTABLE

The relative path of the verify route.

Default: "/oauth/verify"
descriptionstringIMMUTABLE

A description of the scheme.

OIDC Authentication ​

typestringREQUIREDIMMUTABLE

A value of oidc.

providerstringREQUIREDIMMUTABLE

The name of the OIDC provider the login flow uses.

verify_pathstringIMMUTABLE

The relative path of the verify route.

Default: "/oidc/verify"
descriptionstringIMMUTABLE

A description of the scheme.

Basic Authentication ​

typestringREQUIREDIMMUTABLE

A value of basic.

schemesarray[string]IMMUTABLE

An array of strings where values can be: http or https.

Default: ["http"]

API Key Authentication ​

typestringREQUIREDIMMUTABLE

A value of api_key.

schemesarray[string]IMMUTABLE

An array of strings where values can be: http or https.

Default: ["http"]
header_namestringREQUIREDIMMUTABLE
Default: "authorization"

Verify route ​

The oauth2 and oidc schemes add a route that lets a reverse proxy, such as NGINX with auth_request, ask whether a request carries a valid Bondy credential. It is mounted at <base_path>/oauth/verify for oauth2 and <base_path>/oidc/verify for oidc; set verify_path in the Security Object to change it. It verifies against the realm the specification is bound to.

The route accepts GET and HEAD. It reads the credential from the first of these that is present, and does not fall back to a later one if that credential fails:

  1. Authorization: Bearer <credential>
  2. X-Bondy-Ticket: <ticket>
  3. The bondy_ticket_<realm_uri> cookie set by the OIDC login flow

It checks the credential's signature, expiry and revocation; that its scope covers the realm and its issuer is trusted by the realm; that the user is enabled and still exists; and that the realm still allows connections. A credential issued by the OIDC login flow for an identity Bondy does not store locally passes without a local user.

OutcomeStatusResponse
Valid credential200A JSON body with active, authid, authrealm, realm, authroles, authmethod, scope, issued_at, expires_at and expires_in, and the headers x-bondy-authid, x-bondy-authrealm, x-bondy-realm, x-bondy-authroles (comma-separated), x-bondy-authmethod and x-bondy-expires-at.
Anything else401A JSON error body with active: false.

Every failure answers 401, including server-side ones, because NGINX turns any other non-2xx status from auth_request into a 500. The route answers who the caller is, not what they may do.

Loading Specifications at Startup ​

Specifications are usually loaded at runtime through the HTTP API. A node can also load them from a file on every boot.

api_gateway.config_file :: path
Default = noneSince v0.8.8

The path of a JSON file holding one specification object or an array of them. When the key is unset, no file is loaded.

Each node reads the file on every boot, before its listeners start, and stores each valid specification in the replicated store, from where it reaches the other nodes. A specification identical to the stored one is not written again, so an unchanged file produces no replicated writes on reboot.

The file only adds and updates specifications. Removing a specification from the file does not delete it from the store; delete it with the bondy.http_gateway.api.delete WAMP procedure.

Bondy validates every specification in the file before it stores any of them:

  • A missing file logs a warning, and the boot continues.
  • A file that is not valid JSON logs an error. Nothing from it is loaded, and the node does not boot.
  • A specification that fails validation logs an error. No specification from the file is loaded, and the node does not boot.

Default Values ​

Status Codes ​

Every error URI in Bondy's catalogue has a default HTTP status, listed in the HTTP column of the Error Reference. When a wamp_call or wamp_publish action fails and the on_error response sets no status_code, the gateway answers with the default status of the error URI. For a URI that is not in the catalogue, including an application's own error URI, the default status is 500.

Bondy also initialises the API Context status_codes map from the catalogue. The specification's status_codes key overrides or extends that map, at the API level and again at the version level. The map changes a response status only through an expression that reads it, such as {{status_codes |> get({{action.error.error_uri}}, 500) |> integer}} in on_error.status_code:

json
{
    "status_codes": {
        "com.example.error.not_found": 404,
        "bondy.error.timeout": 503
    }
}