Problems with Talk2M DMWeb API through system.net.httpClient and system.net.httpPost

Hello, I’m trying to use eWon’s Talk2M DMWeb API to access to data stored in the cloud. Basically, I’m just testing the ‘getewons’ method, which requires two params, the developer id and Talk2m token, inside the body request (set as x-www-form-urlencoded).
Using Postman I get this result


which is good, because actualy I have not eWon registered on the Talk2M account.
Using Python, with the requests library I get the same result.

Using Ignition 8.1 rc-3, I tried to use system.net.httpClient, here’s the code:

url = "https://data.talk2m.com/getewons"
devId = "6de9e..."
t2mtoken = "pkv8..."

data={"t2mdevid":devId,"t2mtoken":t2mtoken}
headers = {'Content-Type': "application/x-www-form-urlencoded"}
http = system.net.httpClient()
http.post(url=url, data=data, headers=headers).json

And I got this output

{'code': 400L, 'message': u"Missing argument 't2mdevid' for method parameter of type String", 'success': False}

which is the same result I get if I don’t pass the ‘data’ parameter.

I also tried with the system.net.httpPost method, in it’s two forms:

system.net.httpPost(url=url, postParams=data) 
system.net.httpPost(url=url, postData=str(data), headerValues=headers)

In both cases I’m getting this error:

IOError: Server returned HTTP response code: 400 for URL: https://data.talk2m.com/getewons

What am I doing wrong?

Have you tried using “application/json;charset=UTF-8” as your content type? It seems to me like your URL isn’t being encoded correctly with the parameters.

I just tried and I got the same error.

Hm, Maybe try sending your data dictionary as params, instead? I’m guessing at this point, though. I’m not familiar with that particular API.

The API specificies that those two params has to be sent through the request’s body specifying the x-www-form-urlencoded content type, in fact if I try to send them as params with Postman I got another error from the server: “URL query strings are considered unsafe and not allowed when using Token authentication. Put all your parameters in the POST body.”

Anyway, I tried to run a post from Ignition to the postman-echo server and it works, so I gues it’s a DMWeb server side problem. I will try again when I’ll have some eWon attached to the Talk2M account.

@rbabcock thanks for the help! :slight_smile:

1 Like

If your content type is really supposed to be “x-www-form-urlencoded” then your body would be a string that looks like this:

"devId=6de9e...&t2mtoken=pkv8..."

and not a JSON object.

Right! I forgot to encode the data object -_- This will solve the problem when using the httpClient:

import urllib
data=urllib.urlencode({"t2mdevid":devId,"t2mtoken":t2mtoken})

Anyway, I can’t get the httpPost to work

Adding better form submission to httpClient is on the list, but for now, yeah, you have to do it pretty ‘manually’.

I'll pipe in here, 3 years later, and say that if you have a more complex structure, you can't use urlencode, for example (example data to submit metrics to DataDog):

{
  "series": [
    {
      "metric": "system.load.1",
      "type": 0,
      "points": [
        {
          "timestamp": 1636629071,
          "value": 0.7
        }
      ],
      "resources": [
        {
          "name": "dummyhost",
          "type": "host"
        }
      ]
    }
  ]
}

For this you can just jsonEncode the data and pass it into post directly (tbh I'd probably just do this for simple dicts as well):

data={
  "series": [
    {
      "metric": "system.load.1",
      "type": 0,
      "points": [
        {
          "timestamp": 1636629071,
          "value": 0.7
        }
      ],
      "resources": [
        {
          "name": "dummyhost",
          "type": "host"
        }
      ]
    }
  ]
}
data_json = system.util.jsonEncode(data)
http = system.net.httpClient()
response = http.post(url=api_url, data=data_json, headers=headers)
if not response.good:
   print 'Who let the DataDogs out??'

Posterity: If you're just passing JSON, and you want it be encoded as such over the wire, you can (and should) omit system.util.jsonEncode entirely and just pass your dictionary in as the data argument; system.net.httpClient will encode it for you and set the appropriate content-type header.

The urlencode stuff mentioned upstream should only be necessary for form-encoded POST data, a distinct content-type with its own encoding rules that httpClient has no special handling for, for now.

1 Like

Ah, nice. I think I was setting the content-type in my headers manually like a dope :person_facepalming: