You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Configuration/Interfaces/Asterisk-REST-Interface-ARI/ARI-REST-over-WebSocket.md
+92-134
Original file line number
Diff line number
Diff line change
@@ -2,90 +2,51 @@
2
2
3
3
Historically, using ARI required two communications channels... HTTP for making REST requests and getting their reponses, and Websocket for receiving events. Upcoming releases of Asterisk however, will allow you to make REST requests and receive their responses over the same Websocket you use to receive events.
4
4
5
-
## The ASTSwaggerSocket Protocol
5
+
## The Protocol
6
6
7
-
There are several published protocols for request/response type communication over Websockets including [WAMP](https://wamp-proto.org), [JSON-RPC](https://www.jsonrpc.org), [XMPP](https://xmpp.org), [Socket.IO](https://socket.io), etc. but these are all fairly heavyweight and would require significant effort to implement. Instead we went with [SwaggerSocket](https://github.com/swagger-api/swagger-socket) which is a very lightweight JSON encapsulation of HTTP requests and responses and although that project itself is archived, the protocol itself is perfect for our use. We did have to modify it slightly to fit the existing Asterisk ARI implementation (hence "ASTSwaggerSocket") but the changes are trivial. See [Differences between SwaggerSocket and ASTSwaggerSocket](#differences-between-swaggersocket-and-astswaggersocket) below.
8
-
9
-
### Example Handshake
10
-
11
-
Assuming you've already established a Websocket connection to Asterisk, you'll need to start with a handshake before you can send requests.
The handshake only needs to be done once after you've established the websocket. You'll need to use the `identity` when making future requests. Speaking of which, you can now make as many requests as you wish.
7
+
There are several published protocols for request/response type communication over Websockets including [WAMP](https://wamp-proto.org), [JSON-RPC](https://www.jsonrpc.org), [XMPP](https://xmpp.org), [Socket.IO](https://socket.io), etc. but these are all fairly heavyweight and would require significant effort to implement. Instead we went with a simple JSON wrapper loosely based on [SwaggerSocket](https://github.com/swagger-api/swagger-socket).
40
8
41
9
### Request/Response
42
10
11
+
Assuming you've already established a websocket to Asterisk, you can start sending requests without any further setup.
12
+
43
13
Let's say you received a StasisStart event for channel `ast-1741988825.0`. You can now issue a POST request to answer it...
* The `identity` property needs to be the same value that was returned in the `RESTStatusResponse` for the handshake.
63
-
* Although the SwaggerSocket protocol supports sending multiple requests in a single message, our version only looks at the first request in the `requests` array.
64
-
*`uuid` can actually be any string you like. It's returned in the response so you can correlate it to the request that generated it.
28
+
* The `transaction_id` is optional and can be any valid string. It will be returned in the response. You could use this to correlate multiple requests together like creating a channel and adding it to a bridge.
29
+
*`request_id` is also optional and can be any valid string. It will also be returned in the response. You should use this to tie a single request and response together.
65
30
*`method` can be any HTTP method that's valid for the resource you're referencing.
66
-
*`path` is the path to the resource.
31
+
*`uri` is the URI for the resource with optional query parameters but without the leading `/`.
The response is straightforward. The `uuid`will be whatever was specified in the request.
49
+
The response is straightforward. The `transaction_id` and `request_id`will be whatever was specified in the request. Those properties will be present but empty strings if not specified in the request.
You should be able to figure out the response for yourself. The `message_body` is exactly the same JSON response you'd have gotten if you made this GET request via HTTP. It's escaped of course since the response message itself is JSON but you can unmarshall that into its own JSON object using whatever JSON utilities are available for your application programming language.
93
+
You should be able to figure out the response for yourself. The `message_body` is exactly the same JSON response you'd have gotten if you made this GET request via HTTP. It's wrapped for clarity and it's escaped since the response message itself is JSON. You can unmarshall that into its own object using whatever JSON utilities are available for your application programming language.
141
94
142
95
Now let's snoop on that channel...
143
96
144
-
This requires us to send parameters in a query string. The `path` parameter must not include a query string which is why it's named `path` and not `uri`. Instead, query strings are specified with the `query_strings` array.
97
+
This requires us to send parameters to the resource. There are 4 methods for doing this and they are processed in the order below...
We used `query_strings` to specify the snoop arguments but we could also place them in the body of the request as JSON. This requires setting a `Content-Type` header...
129
+
* Using an `application/x-www-form-urlencoded` message body:
We used JSON in the message body but an x-www-form-urlencoded string also works. Since `Content-Type` is a common header, you can specify `content_type` directly instead of in a `headers` array. Don't forget to urlencode the string if it contains a character from the following set `[?&=% ]`. This example is fine as is...
PICK A METHOD! Using more than one method to pass parameters to the resource is highly discouraged because the rules for duplicates are a bit tricky. Of the first 3 methods, the first occurence wins. However, if you also use the 4th method, it will overwrite any earlier values.
There's really only one... You can't get binary data like recordings via the websocket. The frames written to the underlying websocket use the TEXT opcode and the messages are all JSON and while there are ways we could send binary data, they're just too complicated and could interfere with getting asynchronous events. Attempting to retrieve binary data will result in a 406 "Not Acceptable. Use HTTP GET" response.
214
-
215
-
## Differences between SwaggerSocket and ASTSwaggerSocket
216
-
217
-
To fit within the existing ARI archictecture several modifications had to be made to the SwaggerSocket API:
218
-
219
-
* Requests must include a `type` parameter to allow the request to be routed properly.
220
-
* SwaggerSocket uses "camelCase" for protocol parameter names but ARI requires parameter names to be "snake_case".
221
-
* Responses are encapsulated in ARI events which will include the `type`, `timestamp`, `asterisk_id` and `application` parameters.
222
-
* Although the SwaggerSocket protocol supports more than one request in a message, ASTSwaggerSocket will only process the first request in the array.
223
-
* SwaggerSocket's `statusCode` parameter is renamed to `status_code` to comply with the "snake_case" ARI requirement and it's also a JSON number rather than a string. `reasonPhrase` is also renamed to `reason_phrase`.
0 commit comments