OVERVIEW
This guide will show how to expose a Swagger API over WebSockets.This feature is EXPERIMENTAL and is subject to change.
See <https://github.com/jhthorsen/swagger2/blob/master/examples/websocket.pl> for a working example.
DISCLAIMER
This way of exposing Swagger over WebSockets is in no way compatible with <https://github.com/swagger-api/swagger-socket>.SYNOPSIS
Application
package MyApp; use Mojo::Base "Mojolicious"; sub startup { my $app = shift; my $ws = $app->routes->websocket("/ws")->to("events#ws"); $app->plugin(Swagger2 => { url => app->home->rel_file("api.yaml"), ws => $ws, }); }
In the example application class above, we create a custom route object for handling the WebSocket request. The route object $ws is then passed on to the plugin and set up with a default route variable swagger.
The reason why we create a custom websocket route is so it can be used bi-directional, instead of just dispatching to Swagger actions.
Controller
package MyApp::Controller::Events; sub ws { my $c = shift; $c->on(json => sub { my ($c, $data) = @_; return if $c->dispatch_to_swagger($data); }); }
In the example controller above we listen to a json event which can dispatch_to_swagger.
This method will return boolean true if the input looks like a Swagger request.
Request
The input data to the WebSocket need to be JSON and look like this:
{ "id": "some unique string", "op": "operationId", "params": { "paramerName": "value" } }
The ``id'' is used to map the response to a unique request. This means that the ``id'' need to be generated on the client side. The uniqueness requirement is only for this WebSocket connection.
``op'' need to match an operationId in the Swagger specification.
``params'' must be an object where the keys match the parameters in the Swagger specification.
Response
{ "id": "some unique string", "code": 200, "body": {"any":"thing"} }
The response contains the input ``id'', the HTTP status ``code'' and the response from the Swagger action inside ``body''.
JavaScript example
Here is an example JavaScript which can communicate over the socket:
var ws = new WebSocket("ws://example.com/ws"); ws.onopen = function () { ws.send(JSON.stringify({ id: "42", op: "listPets", args: {limit: 60} }); }; ws.onmessage = function (e) { var data = JSON.parse(e.data); if (data.id == "42") { // Response from the request above, because of matching "id" console.log(data.code, data.body); } };
CAVEATS
- ``x-mojo-around-action'' is ignored when issuing WebSocket requests. This may be changed in future version.
- Sharing a WebSocket route object between multiple Swagger plugins is unsupported. (The outcome is unknown)
- The protocol and implementation is subject for change. feedback <https://github.com/jhthorsen/swagger2/issues> is highly appreciated.