:orphan: HTTP Bridge Publisher ===================== Introduction ------------ The *HTTP Publisher* (formerly *HTTP Pusher*) feature is available starting with Crossbar **0.9.5**. The *HTTP Publisher* is a service that allows clients to submit PubSub events via HTTP/POST requests. Crossbar will receive the event data via the request and forward the event via standard WAMP to any connected subscribers in real-time. Try it ------ Clone the `Crossbar.io examples repository `__, and go to the ``rest/publisher`` subdirectory. Now start Crossbar: .. code:: console crossbar start and open http://localhost:8080 in your browser. Open the JavaScript console to see events received. To submit events via HTTP/POST, you can use `curl `__: .. code:: console curl -H "Content-Type: application/json" \ -d '{"topic": "com.myapp.topic1", "args": ["Hello, world"]}' \ http://127.0.0.1:8080/publish ...or any other HTTP/POST capable tool or library. Using Python ------------ To make using the *HTTP Publisher* service even easier, we've created a (trivial) library which you can install by doing: .. code:: console pip install crossbarconnect ``crossbarconnect`` does *not* depend on ``crossbar``, ``autobahn``, ``twisted`` or ``asyncio``. It only uses the Python standard library. It only does HTTP/POST requests. You can publish events from Python like this: .. code:: python import crossbarconnect client = crossbarconnect.Client("http://127.0.0.1:8080/publish") client.publish("com.myapp.topic1", "Hello, world!", 23) The example also contains two Python scripts for testing unsigned requests: .. code:: console python publish.py and signed requests: .. code:: console python publish_signed.py Configuration ------------- The *HTTP Publisher* is configured on a path of a Web transport - here is part of a Crossbar configuration: .. code:: javascript { "workers": [ { "type": "router", ... "transports": [ { "type": "web", ... "paths": { ... "publish": { "type": "publisher", "realm": "realm1", "role": "anonymous" } } } ] } ] } The service dictionary has the following parameters: +---------+----------------------------------------------------------------------------------------------------------------------------------------+ | option | description | +=========+========================================================================================================================================+ | type | MUST be "publisher" (required) | +---------+----------------------------------------------------------------------------------------------------------------------------------------+ | realm | The realm to which the forwarding session is attached that will inject the submitted events, e.g. "realm1"(required) | +---------+----------------------------------------------------------------------------------------------------------------------------------------+ | role | The fixed (authentication) role the forwarding session is authenticated as when attaching to the router-realm, e.g. "role1" (required) | +---------+----------------------------------------------------------------------------------------------------------------------------------------+ | options | A dictionary of options (optional, see below). | +---------+----------------------------------------------------------------------------------------------------------------------------------------+ The ``options`` dictionary has the following configuration parameters: +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | option | description | +=========================+====================================================================================================================================================================================================================================+ | key | A string that when present provides the key from which request signatures are computed. If present, the secret must also be provided. E.g. "myapp1". | +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | secret | A string with the secret from which request signatures are computed. If present, the keymust also be provided. E.g. "kkjH68GiuUZ"). | +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | post_body_limit | An integer when present limits the length (in bytes) of a HTTP/POST body that will be accepted. If the request body exceed this limit, the request is rejected. If 0, accept unlimited length. (default: 0) | +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | timestamp_delta_limit | An integer when present limits the difference (in seconds) between a signature's timestamp and current time. If 0, allow any divergence. (default: 0). | +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | require_ip | A list of strings with single IP addresses or IP networks. When given, only clients with an IP from the designated list are accepted. Otherwise a request is denied. E.g. ["192.168.1.1/255.255.255.0", "127.0.0.1"] (default: -). | +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | require_tls | A flag that indicates if only requests running over TLS are accepted. (default: false). | +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | debug | A boolean that activates debug output for this service. (default: false). | +-------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Running Standalone ------------------ If you only want to run WebSocket and the HTTP Publisher Service (and no other Web path services), here is an example configuration: .. code:: javascript { "version": 2, "workers": [ { "type": "router", "realms": [ { "name": "realm1", "roles": [ { "name": "anonymous", "permissions": [ { "uri": "*", "allow": { "call": true, "register": true, "publish": true, "subscribe": true } } ] } ] } ], "transports": [ { "type": "websocket", "endpoint": { "type": "tcp", "port": 9000 } }, { "type": "web", "endpoint": { "type": "tcp", "port": 8080 }, "paths": { "/": { "type": "publisher", "realm": "realm1", "role": "anonymous" } } } ] } ] } This will run: 1. a WAMP-over-WebSocket endpoint on ``ws://localhost:9000`` 2. a HTTP Push Bridge endpoint on ``http://localhost:8080`` You can test this using .. code:: html and publishing from curl: .. code:: console curl -H "Content-Type: application/json" \ -d '{"topic": "com.myapp.topic1", "args": ["Hello, world"]}' \ http://127.0.0.1:8080/ ``` ## Making Requests To submit events through Crossbar, issue a HTTP/POST request to the URL of the Crossbar HTTP Publisher service with: 1. Content type `application/json` 2. Body containing a JSON object 3. Two query parameters: `timestamp` and `seq` For a call to a HTTP Publisher service, the body MUST be a JSON object with the following attributes: * `topic`: A string with the URI of the topic to publish to. * `args`: An (optional) list of positional event payload arguments. * `kwargs`: An (optional) dictionary of keyword event payload arguments. * `options`: An (optional) dictionary of WAMP publication options (see below). ### Signed Requests Signed requests work like unsigned requests, but have the following additional query parameters. All query parameters (below and above) are mandatory for signed requests. * `key`: The key to be used for computing the signature. * `nonce`: A random integer from [0, 2^53] * `signature`: See below. The signature computed as the Base64 encoding of the following value: HMAC[SHA256]\_{secret} (key \| timestamp \| seq \| nonce \| body) :: Here, `secret` is the secret shared between the publishing application and Crossbar. This value will never travel over the wire. The **HMAC[SHA256]** is computed w.r.t. the `secret`, and over the concatenation key \| timestamp \| seq \| nonce \| body \`\`\` The ``body`` is the JSON serialized event. PHP - Symfony Publisher Bundle ------------------------------ For PHP/Symfony users, there is a bundle which makes publishing via HTTP comfortable - `Crossbar HTTP Publisher Bundle `__ (thanks to `peelandsee `__ for providing this).