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:
- API Object
- Version Object 1
- Path Object 1
HTTP METHOD- ... other HTTP methods
- ... other path objects
- Path Object 1
- ... other version objects
- Version Object 1
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 is incrementally an 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 and API and the behaviour of the Gateway, that is, it also defines its implementation in terms of the actions that the Gateway need to perform.
A Future version of the API Gateway will aligning with Open API. In addition, the API Gateway implementation will be able to produce and serve an Open API specification of the APIs defined in Bondy.
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:
requestRequestObjectThe 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.
securitySecurityObjectAn instance of the Security Object. Its initial value comes from the API Object defaults.security or variables.security property. It is then possibly overridden recursively during evaluation by each [Path Object]#(path-object) definition.
actionobjectAt runtime, it will contain the result or error of the action performed by the API Gateway during the handling of an HTTP request.
variablesmapA 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.
defaultsmapA 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_codesmapA mapping of WAMP Error URIs to HTTP Status Codes, to be used when the Operation Object is a WAMP Action. The entries of this map are recursively updated during evaluation. At each level of the tree this property will merge in the values of the target object's status_codes property, so children nodes can access the entries defined in the ancestors, override them and/or add new status codes to the context.
defaults property.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.
idstringIMMUTABLEA unique tracing identifier for the request
methodstringIMMUTABLEThe HTTP method of the request. One of the following values:
deletegetheadoptionspatchpostput
schemearray[string]IMMUTABLEAn array of strings where values can be: http or https.
peernamestringIMMUTABLEA string representation of the requester IP address and port number e.g. 127.0.0.1:54678.
pathstringIMMUTABLEThe relative path of the request.
hoststringIMMUTABLEThe hostname of the request.
portstringIMMUTABLEThe port number the request.
headers() => mapIMMUTABLEA mapping of HTTP headers to their corresponding values.
languagestringIMMUTABLEThe requested language.
query_stringstringIMMUTABLEThe HTTP query string. See query_params.
query_paramsmapIMMUTABLEA 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"} |
bindingsmapIMMUTABLEA 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"} |
bodyanyIMMUTABLEThe 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_lengthintegerIMMUTABLEThe 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_idintegerIMMUTABLEThe WAMP RESULT.id.
argsarray[any]IMMUTABLEThe WAMP RESULT.args.
kwargs() => mapIMMUTABLEThe WAMP RESULT.kwargs.
HTTP Forward Result
Error Object
TBD
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:
curl -X "POST" "http://localhost:18081/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 String | Evaluates 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.price |> string}} | "13.99" |
{{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 |
{{defaults.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:
- 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. - 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.
API Object
The API object is the root of an API Specification. It contains one or more API Version objects.
idstringREQUIREDIMMUTABLEA global unique identifier for this API.
hoststringREQUIREDIMMUTABLEA 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.
realm_uristringREQUIREDIMMUTABLEThe realm this API will target. An API can only target a single realm.
namestringIMMUTABLEA display name for the API.
variablesmapIMMUTABLEA mapping of arbitrary variable names to values or expressions. This variables can be referenced by expressions in the children objects of this object.
defaultsmapIMMUTABLEA mapping of attributes to their default values. This values are inherited by children objects as defaults when their value is unset.
status_codesmapIMMUTABLEA mapping of WAMP Error URIs to HTTP Status Codes. This values are inherited by children objects as defaults when their value is unset.
versionsarray[VersionObject]REQUIREDIMMUTABLEAn array of Version Object instances.
API Object example
{
"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" : [
...
]
}Version Object
The Version Object represents a particular API version.
base_pathstringREQUIREDIMMUTABLEThe 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.
pathsmapREQUIREDIMMUTABLEA 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_activebooleanIMMUTABLEWhether the path is active.
trueis_deprecatedbooleanIMMUTABLEWhether the path is deprecated i.e. the path will be removed in future versions of the API.
falsepool_sizeintegerIMMUTABLE200infoobjectvariablesmapIMMUTABLEA 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.
defaultsmapIMMUTABLEA 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.
languagesarray[string]IMMUTABLEAn array of language code string.
Version Object example
TBDPath Object
A path specification to be used as a value to a key in the paths property of a Version Object.
summarystringIMMUTABLEA short summary of the API.
descriptionstringIMMUTABLEA description of the API.
variablesmapIMMUTABLEA 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.
defaultsmapIMMUTABLEA 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_collectionbooleanIMMUTABLEDefines whether the resource managed in this path is a collection or not.
falseheaders() => mapIMMUTABLEA mapping of HTTP headers to their corresponding values.
acceptsarray[string]IMMUTABLEAn array of content types. The supported content types are:
application/jsonapplication/json; charset=utf-8application/msgpackapplication/msgpack; charset=utf-8application/x-www-form-urlencoded
providesarray[string]IMMUTABLEAn array of content types. The supported content types are:
application/jsonapplication/json; charset=utf-8application/msgpackapplication/msgpack; charset=utf-8
schemesarray[string]IMMUTABLEAn array of strings where values can be: http or https.
body_max_bytesintegerIMMUTABLEbody_read_bytesintegerIMMUTABLEbody_read_secondsintegerIMMUTABLEtimeoutintegerIMMUTABLEwamp.call_timeout (See reference).connect_timeoutintegerIMMUTABLEretriesintegerIMMUTABLEretry_timeoutintegerIMMUTABLEdeleteOperationObjectIMMUTABLEThe operation specification to perform in case the API Gateway receives an HTTP DELETE Request.
getOperationObjectIMMUTABLEThe operation specification to perform in case the API Gateway receives an HTTP GET Request.
headOperationObjectIMMUTABLEThe operation specification to perform in case the API Gateway receives an HTTP HEAD Request.
optionsOperationObjectIMMUTABLEThe operation specification to perform in case the API Gateway receives an HTTP OPTIONS Request.
patchOperationObjectIMMUTABLEThe operation specification to perform in case the API Gateway receives an HTTP PATCH Request.
postOperationObjectIMMUTABLEThe operation specification to perform in case the API Gateway receives an HTTP POST Request.
putOperationObjectIMMUTABLEThe operation specification to perform in case the API Gateway receives an HTTP PUT Request.
Path Object example
{
"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
infostringIMMUTABLEbody_max_bytesintegerIMMUTABLEbody_max_byte value.body_read_bytesintegerIMMUTABLEbody_read_bytes value.body_read_secondsintegerIMMUTABLEbody_read_seconds value.Operation Object example
TBDAction Object
The API Gateway currently supports 3 types of actions.
Static Action
An action that returns a static response.
typestringREQUIREDIMMUTABLEThe value static.
headers() => mapIMMUTABLEA mapping of HTTP headers to their corresponding values.
body() => anyIMMUTABLEThe body to be returned with the response.
Action Object example
TBDForward Action
An action that forwards the incoming HTTP request to an upstream HTTP endpoint.
typestringREQUIREDIMMUTABLEThe value forward.
http_methodstringREQUIREDIMMUTABLEThe HTTP method to be used when forwarding the request to the upstream endpoint. It must be on of the HTTP methods:
deletegetheadoptionspatchpostput
host() => stringREQUIREDIMMUTABLEThe upstream host.
path() => stringREQUIREDIMMUTABLEThe upstream path.
query_string() => stringIMMUTABLEThe upstream query string.
headers() => mapIMMUTABLEA mapping of HTTP headers to their corresponding values.
body() => anyIMMUTABLEThe body to be forwarded to the upstream endpoint.
connect_timeout() => integerIMMUTABLEretries() => integerIMMUTABLEretry_timeout() => integerIMMUTABLEForward Action Object example
TBDWAMP Action
An action that transforms an incoming HTTP request to a WAMP operation.
typestringREQUIREDIMMUTABLEOne of the following values:
wamp_callwamp_publish
argsarray[() => any]IMMUTABLEThe WAMP message args.
[]kwargs() => mapIMMUTABLEThe WAMP message kwargs.
{}timeout() => integerIMMUTABLEconnect_timeout() => integerIMMUTABLEretries() => integerIMMUTABLEretry_timeout() => integerIMMUTABLEWAMP Action example
{
...
"paths": {
"/accounts" : {
"post": {
"action": {
"type": "wamp_call",
"procedure": "com.example.account",
"options": {"timeout": 15000},
"args" : ["{{request.body}}"],
"kwargs" : {}
},
"response": {,
...
}
}
}
}
}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_resultobjectREQUIREDA declaration of the desired HTTP response in case the action (as defined in the sibling action object) was successful.
on_errorobjectREQUIREDA declaration of the desired HTTP response in case the action (as defined in the sibling action object) failed.
WAMP Response Object Example
{
...
"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]IMMUTABLEAn array of strings where values can be: http or https.
acceptsarray[string]IMMUTABLEAn array of content types. The supported content types are:
application/jsonapplication/json; charset=utf-8application/msgpackapplication/msgpack; charset=utf-8application/x-www-form-urlencoded
["application/json", "application/msgpack"]providesarray[string]IMMUTABLEAn array of content types. The supported content types are:
application/jsonapplication/json; charset=utf-8application/msgpackapplication/msgpack; charset=utf-8
["application/json", "application/msgpack"]headers() => mapIMMUTABLEA mapping of HTTP headers to their corresponding values.
{}body_max_bytesintegerIMMUTABLEbody_read_bytesintegerIMMUTABLEbody_read_secondsintegerIMMUTABLEtimeout() => integerIMMUTABLEconnect_timeout() => integerIMMUTABLEretries() => integerIMMUTABLEretry_timeout() => integerIMMUTABLESecurity Object
The Security Object defines the authentication method to be used for an API Version. The supported authentication methods are:
- Basic Authentication
- API Key
- OAuth2
- Client Credentials
- Resource Owner Password
Basic Authentication
typestringREQUIREDIMMUTABLEA value of basic.
schemesarray[string]IMMUTABLEAn array of strings where values can be: http or https.
["http"]API Key Authentication
typestringREQUIREDIMMUTABLEA value of api_key.
schemesarray[string]IMMUTABLEAn array of strings where values can be: http or https.
["http"]header_namestringREQUIREDIMMUTABLE"authorization"WARNING
CURRENTLY NOT IMPLEMENTED
OAuth2 AUthentication
typestringREQUIREDIMMUTABLEA value of oauth2.
schemesarray[string]IMMUTABLEAn array of strings where values can be: http or https.
["http"]flowstringREQUIREDIMMUTABLEOne of the following values:
implicitauthorization_codeclient_credentialsresource_owner_password_credentials
token_pathstringIMMUTABLEThe relative path to use for the obtain/refresh token action.
"/oauth/token"revoke_token_pathstringIMMUTABLEThe relative path to use for the revoke token action.
"/oauth/revoke"Default Values
Status Codes
The following are the default values used to initialise the API Context.
{
"bondy.error.already_exists": 400, // BAD REQUEST
"bondy.error.not_found": 404, // NOT FOUND
"bondy.error.bad_gateway": 504, // SERVICE UNAVAILABLE
"bondy.error.http_gateway.invalid_expression": 500, // INTERNAL SERVER ERROR,
"bondy.error.timeout": 504, // GATEWAY TIMEOUT
"wamp.error.authorization_failed": 500, // INTERNAL SERVER ERROR,
"wamp.error.canceled": 400, // BAD REQUEST
"wamp.error.close_realm": 500, // INTERNAL SERVER ERROR,
"wamp.error.disclose_me_not_allowed": 400, // BAD REQUEST
"wamp.error.goodbye_and_out": 500, // INTERNAL SERVER ERROR,
"wamp.error.invalid_argument": 400, // BAD REQUEST
"wamp.error.invalid_uri": 400, // BAD REQUEST
"wamp.error.net_failure": 502, // BAD GATEWAY
"wamp.error.not_authorized": 403, // FORBIDDEN
"wamp.error.no_eligible_callee": 502, // BAD GATEWAY
"wamp.error.no_such_procedure": 501, // NOT IMPLEMENTED
"wamp.error.no_such_realm": 502, // BAD GATEWAY
"wamp.error.no_such_registration": 502, // BAD GATEWAY
"wamp.error.no_such_role": 400, // BAD REQUEST
"wamp.error.no_such_session": 500, // INTERNAL SERVER ERROR,
"wamp.error.no_such_subscription": 502, // BAD GATEWAY
"wamp.error.option_disallowed_disclose_me": 400, // BAD REQUEST
"wamp.error.option_not_allowed": 400, // BAD REQUEST
"wamp.error.procedure_already_exists": 400, // BAD REQUEST
"wamp.error.system_shutdown": 500 // INTERNAL SERVER ERROR
}