Search code examples
fiwarefiware-orion

Orion Context Broker - subscriptions


I have a small problem. Im doing a subscription to Orion Context Broker and I have a strange problem with URL of callback: this code works from tutorial:

{
   "entities": [
        {
            "type": "Room",
            "isPattern": "false",
            "id": "Room1"
        }
    ],
    "attributes": [
        "temperature"
    ],
    "reference": "http://localhost:1028/accumulate",
    "duration": "P1M",
    "notifyConditions": [
        {
            "type": "ONTIMEINTERVAL",
            "condValues": [
                "PT10S"
            ]
        }
    ]
}

But this code doesnt work:

{
    "entities": [
        {
            "type": "Room",
            "isPattern": "false",
            "id": "Room1"
        }
    ],
    "attributes": [
        "temperature"
    ],
    "reference": "http://192.168.1.12:1028/accumulate?name=dupex",
    "duration": "P1M",
    "notifyConditions": [
        {
            "type": "ONTIMEINTERVAL",
            "condValues": [
                "PT10S"
            ]
        }
    ]
}

Only difference is reference field: "reference": "192.168.1.12:1028/accumulate?name=dupex"

I got:

{
    "subscribeError": {
        "errorCode": {
            "code": "400",
            "reasonPhrase": "Bad Request",
            "details": "Illegal value for JSON field"
        }
    }
}

Any Suggestion please :) thank you.


Solution

  • The root cause of the problem is that = is a forbidden character, not allowed in payload request for security reasons (see this section in the user manual about it).

    There are two possible workarounds:

    1. Avoid the usage of query strings in the URL for reference in subscribeContext, e.g. using http://192.168.1.12:1028/accumulate/name/dupex.
    2. Encode URL encoding to avoid forbidden characters (in particular, the code for = is %3D) and prepare your code to decode it.

    In case 2, you could use the follwoing reference in subscribeContext: http://192.168.1.12:1028/accumulate?name%3Ddupex. Then, an example of code that will take into account the encoding and get the name argument properly would be the following (written in Python using Flask as REST server framework):

    from flask import Flask, request
    from urllib import unquote
    from urlparse import urlparse, parse_qs
    app = Flask(__name__)
    
    @app.route("/accumulate")
    def test():
        s = unquote(request.full_path) # /accumulate?name%3Dduplex -> /accumulate?name=duplex
        p = urlparse(s)                # extract the query part: '?name=duplex'
        d = parse_qs(p.query)          # stores the query part in a Python dictionary for easy access
        name= d['name'][0]             # name <- 'duplex'
        # Do whatever you need with the name...
        return ""
    
    if __name__ == "__main__":
        app.run()
    

    I guess that a similar approach can be used in other languages (Java, Node, etc.).

    EDIT: Orion version 1.2 support notification customization in the NGSIv2, which allows this use case. For example, you can define the following subscriptions:

    {
      ..
      "notification": {
        "httpCustom": {
          "url": "http://192.168.1.12:1028/accumulate",
          "qs": {
            "name": "dupex"
          }
        }
        ..
      }
      ..
    }
    

    Please have a look to "Subscriptions" and "Custom Notifications" sections at NGSIv2 Specification for details.