Page 1 of 1

Python - How to POST JSON data

Posted: Sunday 14 January 2018 23:50
by Domoticx
Hi all,

I have searched and tested for 9 hours now, and i cannot figure out how to make a (seemly simple) JSON POST (not a http url request/get) using Domoticz json.htm url.

I do NOT preffer sending/updating data for bussiness customers over a URL request (GET), like this:

Code: Select all

http://192.168.1.1:8080/json.htm?type=command&param=udevice&idx=1&nvalue=15
Why? Because data you are sending with this method is visible on the network (tcp/wifi sniffer) and not encoded with an URL request, when using a POST u can use HTTPS, so data is send encoded after the HTTPS TCP tunnel is created.

Now....all i get back is ERR, in the wiki is stated a pass is needed, so setting domoticz config:

name "jan"
pass "1234"
Basic-Auth

But nevertheless i cannot get it to work....maybe i am overlooking something....any ideas? :roll:

TESTSCRIPT
-----------------------------------------------------------------------------------------------------------
#!/usr/bin/python
import subprocess
import time
import os
import urllib2, urllib
import base64
import requests
import json
from requests.auth import HTTPBasicAuth

serverIP = "192.168.1.1:8080"
#serverIP = "localhost:8080"
deviceId = 1
base64string = base64.b64encode('%s:%s' % ("jan", "1234"))

#currentTemp = subprocess.check_output(["/opt/vc/bin/vcgencmd","measure_temp"])
#currentTemp = float(currentTemp.split("=")[1][:-3])
payload = {'type': 'command', 'param': 'udevice', 'idx': '1', 'nvalue': '0', 'svalue': '55'}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
headers64 = {'Content-type': 'application/json', 'Accept': 'text/plain', 'Authorization': 'Basic %s' % base64string}

print 'Authorization: Basic %s' % base64string

r = requests.post("http://" + serverIP + "/json.htm",data={'type':'command', 'param':'udevice', 'idx':1, 'nvalue':0, 'svalue':55}, headers=headers)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", data=payload, headers=headers)
print r.status_code, r.reason
print r.text

r = requests.post("http://192.168.1.1:8080/json.htm", "amFuOkpBTg==", json={'type': 'command', 'param': 'udevice', 'idx': '1', 'nvalue': '0', 'svalue': '55'}, headers=headers)
print r.status_code, r.reason
print r.text

r = requests.post("http://192.168.2.12:8080/json.htm", json={'type': 'command', 'param': 'udevice', 'idx': '1', 'nvalue': '0', 'svalue': '55'}, headers={"Authorization": "Basic amFuOkpBTg=="})
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", auth=HTTPBasicAuth('jan', '1234'), data=json.dumps(payload), headers=headers)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", auth=HTTPBasicAuth('jan', '1234'), data=json.dumps(payload))
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", auth=HTTPBasicAuth('jan', '1234'), data=payload, headers=headers)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", auth=HTTPBasicAuth('jan', '1234'), data=payload)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", auth=HTTPBasicAuth('jan', '1234'), json=payload)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", auth=HTTPBasicAuth('jan', '1234'), json=json.dumps(payload))
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", auth=HTTPBasicAuth('jan', '1234'), json=payload, headers=headers)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", json=payload, headers=headers64)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", data=payload, headers=headers64)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", json=json.dumps(payload), headers=headers64)
print r.status_code, r.reason
print r.text

r = requests.post("http://" + serverIP + "/json.htm", data=json.dumps(payload), headers=headers64)
print r.status_code, r.reason
print r.text
-----------------------------------------------------------------------------------------------------------

RESULT
Authorization: Basic amFuOkpBTg==
200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

200 OK
{
"status" : "ERR"
}

Re: Python - How to POST JSON data

Posted: Monday 15 January 2018 8:32
by freijn
I am not well knowledged in this, but first item I see is....

Why are you still using 8080 ?
Should it not be 443 ?

Cheers,

Frank

Re: Python - How to POST JSON data

Posted: Monday 15 January 2018 16:36
by Domoticx
Hi Frank,

Thanks for your input.

Eventually...maybe....but for now a normal HTTP connection should also work on 8080 as in the stated example above.

Re: Python - How to POST JSON data

Posted: Monday 15 January 2018 19:47
by malarcy
To get the info from domoticz you need to use GET not POST.

The response is in JSON - not the query.

GET over HTTPS does not expose the remainder of the URL - wireshark it if you don't agree - SSL handshake basically does the high level bit first, something like

connect to www.myfakedomain.com:443
do - some - ssl - magic
now request GET /whatever.html?parameters=1
if authentication required - then server returns a 401 - unauthorized (from memory) - then the requesting end will provide the auth that you gave in the headers.

So the traffic is encrypted once conversation is established.

You appear to be confusing authentication (username/password) with encryption, so, in your examples, if you have authentication enabled, you need to GET the full URL with the auth headers ( but as you correctly state - that will all go in the clear over the internet)

You can then do the same thing with HTTPS (using the correct port - but you may need to look out for self signed certificates - don't know - not tried) - and the crucial parts of the exchange - the username/password, the request and the response will be encrypted.

Suggest you fire up wireshark and watch an HTTP vs HTTPS exchange (from a browser) - to see the difference.

Then add the auth headers and see how that looks again in wireshark

Hope this helps

Re: Python - How to POST JSON data

Posted: Monday 15 January 2018 21:45
by Domoticx
Hi malarcy,

Oh man and i just thought that it also accepted JSON POST requests.... :cry:

Thanks for clearing up the GET is also encoded using HTTPS protocol, eventually i will test this out sometimes with wireshark ;)