Page 1 of 1

add payload to POST request

Posted: Wed Jun 29, 2022 9:00 am
by Miliks
Hi guys,
i have a server with POST e REST services. Using micropython i need to perform POST request.
GET is performed and respond correctly using the following format:

s.send(b"GET /sensordata/premises HTTP/1.1\r\nHost:XX.XXX.XXX.XXX\r\n" + "Accept: application/json\r\n\r\n")

but for the POST looks like the request arrived at server, but the payload body is empty. For some reason, the JSON body of the request is not interpreted in the correct way.

Code: Select all

from network import WLAN
import socket
import machine
import time
import struct
import json
import pycom

wlan = WLAN(mode=WLAN.STA)
wlan.connect("*****", auth=(WLAN.WPA2, "*****"), timeout=5000)

while not wlan.isconnected():
    machine.idle()
print("Connected to WiFi\n")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
url = 'XX.XXX.XXX.XXX'

sockaddr = socket.getaddrinfo(url, 80) [0][-1]
s.connect(sockaddr)

print('socket connected')

httpreq = b'POST /sensordata/insertrecords HTTP/1.1 \r\n Host:XX.XXX.XXX.XXX \r\n' + 'Accept: application/json \r\n' + 'Content-Type: application/json\r\n\r\n' + ' {\"node_id\":\"1\",\"value\":[{\"measure_time_stamp\":\"2020-10-06T09:25:43\",\"temp\":\"14\",\"humidity\":\"75\",\"ph1\":11,\"ph2\":12,\"ph3\":13}]}'
s.send(httpreq)
time.sleep(1)
rec_bytes = s.recv(4096)
print("RESPONSE = " + str(rec_bytes))
print('end')
s.close()

Re: add payload to POST request

Posted: Wed Jun 29, 2022 12:03 pm
by ChrisO
I haven't done this before, but I'm guessing you need to add the Content-Length header is well.

Re: add payload to POST request

Posted: Wed Jun 29, 2022 12:07 pm
by ChrisO
someone will come along with a full fledged example, I'm sure.
In the meantime, if you won't want to wait. I'd take a cpython example like the one discussed here:
https://stackoverflow.com/questions/286 ... parameters

besides Content-Length it seems like you have to byte encode the information as well.

Re: add payload to POST request

Posted: Wed Jun 29, 2022 1:29 pm
by p_j
Have you considered using 'requests', it might be easier and less error prone?

Code: Select all

import urequests as requests

mydata = {'temp': 10, }

x = requests.post(url, json=mydata)
if x.status_code == 200:
    print("Done")
    

Re: add payload to POST request

Posted: Wed Jun 29, 2022 2:56 pm
by Miliks
ChrisO wrote:
Wed Jun 29, 2022 12:07 pm
someone will come along with a full fledged example, I'm sure.
In the meantime, if you won't want to wait. I'd take a cpython example like the one discussed here:
https://stackoverflow.com/questions/286 ... parameters

besides Content-Length it seems like you have to byte encode the information as well.
thanks, this was really helpful, it was really a matter of encoding and content-length parameters. the code below works perfectly:

Code: Select all

headers =  """\
POST /sensordata/insertrecords HTTP/1.1
Content-Type: {content_type}\r
Content-Length: {content_length}\r
Host: {host}\r
Connection: close\r
\r\n"""
                               
body_bytes = json_data.encode('ascii')
header_bytes = headers.format(
    content_type="application/json",
    content_length=len(body_bytes),
    host=str(host) + ":" + str(port)
).encode('iso-8859-1')

payload = header_bytes + body_bytes

s.sendall(payload)

Re: add payload to POST request

Posted: Wed Jun 29, 2022 11:40 pm
by jimmo
Miliks wrote:
Wed Jun 29, 2022 2:56 pm
thanks, this was really helpful, it was really a matter of encoding and content-length parameters. the code below works perfectly:
Unless you're really optimising for every last byte of RAM and flash, then using urequests would be simpler -- see https://github.com/micropython/micropyt ... equests.py (it might already be installed on your device, e.g. ESP32!)