how to use http bridge callee?

#1

All,

I’m finding the docs a little lacking for HTTP bridge services:

http://crossbar.io/docs/HTTP-Bridge-Services-Callee/

BACKGROUND

I’m modifying a C# application that runs on Windows in the system tray. This application waits for print jobs that come from the web, downloads the job as HTML and sends the job to a configured local printer. Currently the application will poll a production web server every 1 minute and see if any print jobs exist. Enter crossbar! What I’m planning to do is have the C# application connect to crossbar instead and subscribe to print job topics. Now, when a print job is available, a PUBLISH will trigger this application to download/print the print job. Awesome. No more polling.

TOO MANY PARTS TO BUILD

With the polling strategy, the C# application talks to a web server. The web server can use PHP 7 and the PHP 7 script comes to life and dies after the HTTP request. This means we don’t need to have a client connected (daemon, worker, container, etc … whatever you wanna call it) just to service the HTTP requests. Apache+PHP act as the client and these are already configured and running for other tasks anyhow.

Rather than build a custom client to handle the print requests for Crossbar, I wanted to use the REST bridging and have configured crossbar as follows:

{
    "type": "container",
    "options": {
        "pythonpath": [
            ".."
        ]
    },
    "components": [
        {
            "type": "class",
            "classname": "crossbar.adapter.rest.RESTCallee",
            "realm": "realm1",
            "extra": {
                "procedure": "api.print",
                "baseurl": "http://dante.domain"
            },
            "transport": {
                "type": "websocket",
                "endpoint": {
                    "type": "tcp",
                    "host": "127.0.0.1",
                    "port": 8080
                },
                "url": "ws://127.0.0.1:8080/ws"
            }
        }
    ]
}


So, now I can call this URL through crossbar (from JS for example) as if it were an RPC call:

// test pfwapi call ...
session.call('api.print', [], {method: 'GET', url: 'api/print/test', params: {token: 'dante'}}).then(
    function (res) {
        console.log("print api call result:", res);
    },
    function (err) {
        console.log("print api call error:", err);
    }
);

Thing is that I don't really know how to use the HTTP-Bridge-Services-Callee stuff. The documentation doesn't tell me ...

1) how to return an error from the PHP URL at http://dante.domain/api/print/test
Am I supposed to return HTTP status code 500? Is any HTTP status other than 200 considered an error?
Examples of errors I might need to return are ...


invalid passphrase
missing print job
invalid print job
  ... etc

Should these become part of the HTTP response?

  <?php

header($_SERVER[‘SERVER_PROTOCOL’] . ’ 500 Invalid Print Job’, true, 500);
exit;

I am trying to throw an error, but all my attempts continue to trigger the RESULT and never an ERROR.

  1. Does ERROR not exist?

I’d expect that status=200 considered “successful” result and everything else is an error … maybe?

  1. What is the format of the returned data for successful or error call results?

Right now I’m seeing ‘code’, ‘content’, and ‘headers’ in my results … what should I expect here? Seeing ‘code’ leads me to believe that I might see something other than “200” and might confuse what I expect from #2 above.

Finally, in crossbar, I’m seeing the following …

2016-05-13T18:38:27-0500 [Container 1463] Starting factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3d60>

2016-05-13T18:38:28-0500 [Container 1463] Stopping factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3d60>

2016-05-13T18:38:29-0500 [Container    1463] Starting factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3da0>

2016-05-13T18:38:29-0500 [Container    1463] Stopping factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3da0>

And I see one Start/Stop for each RPC request I make through crossbar. Does that mean this HTTP bridge is expensive?

My whole objective it to be able to write only crossbar clients with JS and through C# and leave the API as an HTTP implementation so I can leverage

Apache/PHP as the client that implements the RPC backend for most API calls.

Am I not supposed to be doing it this way?

– Dante

0 Likes

#2

Hi Dante,

The Callee does not return an “error” unless the web request was unable to be completed. For example, if the host is down, or the hostname can’t be found. It returns a success result no matter the HTTP status code – this is to avoid declaring anything but 200 a “success” and potentially hamstringing it for uses that we didn’t envision, or for web APIs that use different or non-standard status codes. So, it is up to you to decide what codes count as “errors” or “success” for your application and check for them. The response format is indeed a dictionary of code + content + headers.

The start/stop is for the HTTP client factory – it is not expensive, but the reason why new factories are started and stopped so often is that in the factory+protocol pattern, you end up with a “one-shot” factory that produces a single protocol (which then connects to the URL). Factories in Python+Twisted are extremely cheap, so there’s nothing to worry about there.

As far as your implementation, it appears to be sound, although the most efficient way of implementing it may be to use something like Thruway (https://github.com/voryx/Thruway) to communicate with Crossbar persistently, although you have mentioned that this approach is less optimal for your situation. The REST bridge is meant as more of a way of hooking existing systems into Crossbar.

  • Amber
···

On Saturday, 14 May 2016 07:47:53 UTC+8, Dante Lorenso wrote:

All,

I’m finding the docs a little lacking for HTTP bridge services:

http://crossbar.io/docs/HTTP-Bridge-Services-Callee/

BACKGROUND

I’m modifying a C# application that runs on Windows in the system tray. This application waits for print jobs that come from the web, downloads the job as HTML and sends the job to a configured local printer. Currently the application will poll a production web server every 1 minute and see if any print jobs exist. Enter crossbar! What I’m planning to do is have the C# application connect to crossbar instead and subscribe to print job topics. Now, when a print job is available, a PUBLISH will trigger this application to download/print the print job. Awesome. No more polling.

TOO MANY PARTS TO BUILD

With the polling strategy, the C# application talks to a web server. The web server can use PHP 7 and the PHP 7 script comes to life and dies after the HTTP request. This means we don’t need to have a client connected (daemon, worker, container, etc … whatever you wanna call it) just to service the HTTP requests. Apache+PHP act as the client and these are already configured and running for other tasks anyhow.

Rather than build a custom client to handle the print requests for Crossbar, I wanted to use the REST bridging and have configured crossbar as follows:

{
    "type": "container",
    "options": {
        "pythonpath": [
            ".."
        ]
    },
    "components": [
        {
            "type": "class",
            "classname": "crossbar.adapter.rest.RESTCallee",
            "realm": "realm1",
            "extra": {
                "procedure": "api.print",
                "baseurl": "[http://dante.domain](http://dante.domain)"
            },
            "transport": {
                "type": "websocket",
                "endpoint": {
                    "type": "tcp",
                    "host": "127.0.0.1",
                    "port": 8080
                },
                "url": "ws://[127.0.0.1:8080/ws](http://127.0.0.1:8080/ws)"
            }
        }
    ]
}



So, now I can call this URL through crossbar (from JS for example) as if it were an RPC call:


// test pfwapi call ...
session.call('api.print', [], {method: 'GET', url: 'api/print/test', params: {token: 'dante'}}).then(
    function (res) {
        console.log("print api call result:", res);
    },
    function (err) {
        console.log("print api call error:", err);
    }
);


Thing is that I don't really know how to use the HTTP-Bridge-Services-Callee stuff. The documentation doesn't tell me ...


1) how to return an error from the PHP URL at [http://dante.domain/api/print/test](http://dante.domain/api/print/test)
Am I supposed to return HTTP status code 500? Is any HTTP status other than 200 considered an error?
Examples of errors I might need to return are ...



invalid passphrase
missing print job
invalid print job
  ... etc


Should these become part of the HTTP response?


  <?php

header($_SERVER[‘SERVER_PROTOCOL’] . ’ 500 Invalid Print Job’, true, 500);
exit;

I am trying to throw an error, but all my attempts continue to trigger the RESULT and never an ERROR.

  1. Does ERROR not exist?

I’d expect that status=200 considered “successful” result and everything else is an error … maybe?

  1. What is the format of the returned data for successful or error call results?

Right now I’m seeing ‘code’, ‘content’, and ‘headers’ in my results … what should I expect here? Seeing ‘code’ leads me to believe that I might see something other than “200” and might confuse what I expect from #2 above.

Finally, in crossbar, I’m seeing the following …

2016-05-13T18:38:27-0500 [Container 1463] Starting factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3d60>

2016-05-13T18:38:28-0500 [Container 1463] Stopping factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3d60>

2016-05-13T18:38:29-0500 [Container    1463] Starting factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3da0>

2016-05-13T18:38:29-0500 [Container 1463] Stopping factory <twisted.web.client._HTTP11ClientFactory instance at 0x00000000021f3da0>


And I see one Start/Stop for each RPC request I make through crossbar. Does that mean this HTTP bridge is expensive?


My whole objective it to be able to write only crossbar clients with JS and through C# and leave the API as an HTTP implementation so I can leverage
Apache/PHP as the client that implements the RPC backend for most API calls.


Am I not supposed to be doing it this way?


-- Dante



0 Likes