Can't send HTTP post request in my wanted format - python

I want to send a post request but I don't know how to send the data in the way I need it.
The data of the request when I sniff should look like this only(because it looks like this when I sniff while I am using the website):
[username, password]
but I don't know how to send it differently from the format of JSON: username=name&password=pass
Here is what I tried, but it didn't work.
postdata = ["victor", "asdasd"]
resp = requests.post(SERVER_IP, data=postdata)
I expect it to send the data as I wrote but I got an error that said: ValueError: too many values to unpack (expected 2)

try to encode postdata as bytes:
postdata = ["victor", "asdasd"]
resp = requests.post(SERVER_IP, data=str(postdata).encode())
data can be a bytes objects, as per the docstring:
:param data: (optional) Dictionary, list of tuples, bytes, or file-like
object to send in the body of the :class:`Request`.

Related

ValueError: Data must not be a string. in Python [duplicate]

I am trying to do the following with requests:
data = {'hello', 'goodbye'}
json_data = json.dumps(data)
headers = {
'Access-Key': self.api_key,
'Access-Signature': signature,
'Access-Nonce': nonce,
'Content-Type': 'application/json',
'Accept': 'text/plain'
}
r = requests.post(url, headers=headers, data=json_data,
files={'file': open('/Users/david/Desktop/a.png', 'rb')})
However, I get the following error:
ValueError: Data must not be a string.
Note that if I remove the files parameter, it works as needed. Why won't requests allow me to send a json-encoded string for data if files is included?
Note that if I change data to be just the normal python dictionary (and not a json-encoded string), the above works. So it seems that the issue is that if files is not json-encoded, then data cannot be json-encoded. However, I need to have my data encoded to match a hash signature that's being created by the API.
When you specify your body to a JSON string, you can no longer attach a file since file uploading requires the MIME type multipart/form-data.
You have two options:
Encapsulate your JSON string as part as the form data (something like json => json.dumps(data))
Encode your file in Base64 and transmit it in the JSON request body. This looks like a lot of work though.
1.Just remove the line
json_data = json.dumps(data)
and change in request as data=data.
2.Remove 'Content-Type': 'application/json' inside headers.
This worked for me.
Alternative solution to this problem is to post data as file.
You can post strings as files. Read more here:
http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file
Here is explained how to post multiple files:
http://docs.python-requests.org/en/latest/user/advanced/#post-multiple-multipart-encoded-files
removing the following helped me in my case:
'Content-Type': 'application/json'
then the data should be passed as dictionary
If your files are small, you could simply convert the binary (image or anything) to base64 string and send that as JSON to the API. That is much simpler and more straight forward than the suggested solutions. The currently accepted answer claims that is a lot of work, but it's really simple.
Client:
with open('/Users/houmie/Downloads/log.zip','rb') as f:
bytes = f.read()
tb = b64encode(bytes)
tb_str = tb.decode('utf-8')
body = {'logfile': tb_str}
r = requests.post('https://prod/feedback', data=json.dumps(body), headers=headers)
API:
def create(event, context):
data = json.loads(event["body"])
if "logfile" in data:
tb_back = data["logfile"].encode('utf-8')
zip_data = base64.b64decode(tb_back)

sending raw data in python requests

I'm trying to send a POST request with python requests, containing the following data:
__VIEWSTATE=%2FwEPDwUJODgwODc4MzI2D2QWBAIEDxYCHgdWaXNpYmxlaGQCBg8WAh8AZxYCZg9kFhBmDw8WAh4EVGV4dAUl16jXmdep15XXnSDXntep16rXntepINeX15PXqSDXnNeQ16rXqGRkAgEPFgIeBWNsYXNzBSNmb3JtLWdyb3VwIGhhcy1mZWVkYmFjayBoYXMtc3VjY2VzcxYIAgEPDxYCHwEFLSog16nXnSDXntep16rXntepICjXkdeZ158gNCDXnCAxMiDXqteV15nXnSkgOmRkAgUPDxYCHwBoZGQCBw8PFgQeCENzc0NsYXNzZR4EXyFTQgICFgIfAgUwZ2x5cGhpY29uIGZvcm0tY29udHJvbC1mZWVkYmFjayBnbHlwaGljb24tcmVtb3ZlZAIJDxYGHwIFE2FsZXJ0IGFsZXJ0LXN1Y2Nlc3MeBXN0eWxlBQ5kaXNwbGF5OmJsb2NrOx4JaW5uZXJodG1sBRjXqdedINee16nXqtee16kg16TXoNeV15lkAgIPFgIfAGgWAmYPFgIfAgUXZm9ybS1ncm91cCBoYXMtZmVlZGJhY2sWBAIDDw8WBB8DZR8EAgJkZAIFDxYCHwUFDWRpc3BsYXk6bm9uZTtkAgMPFgIfAgUXZm9ybS1ncm91cCBoYXMtZmVlZGJhY2sWBgIBDw8WAh8AaGRkAgUPDxYEHwNlHwQCAmRkAgcPFgIfBQUNZGlzcGxheTpub25lO2QCBA8WAh8CBRdmb3JtLWdyb3VwIGhhcy1mZWVkYmFjaxYEAgMPDxYEHwNlHwQCAmRkAgUPFgIfBQUNZGlzcGxheTpub25lO2QCBQ8WAh8CBRdmb3JtLWdyb3VwIGhhcy1mZWVkYmFjaxYEAgMPDxYEHwNlHwQCAmRkAgUPFgIfBQUNZGlzcGxheTpub25lO2QCEw8WAh8CBRdmb3JtLWdyb3VwIGhhcy1mZWVkYmFjaxYEAgUPD2QWAh8FBQ1kaXNwbGF5Om5vbmU7ZAIHDw8WBB8DZR8EAgJkZAIXDxYGHwIFEmFsZXJ0IGFsZXJ0LWRhbmdlch8FBQ5kaXNwbGF5OmJsb2NrOx8GBSjXl9eV15HXlCDXnNeQ16nXqCDXkNeqINeq16DXkNeZINeU15DXqteoZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAwUJYWxsb3dtYWlsBQhTZW5kTmV3cwUIY2hrdGVybXNHWETH5Z00Bw%2FRQ%2BPP7XKuKE1Yc7MfMt6j3NmJGEldOg%3D%3D&__VIEWSTATEGENERATOR=98F5786E&__EVENTVALIDATION=%2FwEWPwLc4fuhDgLPv6LBCALyveCRDwKt9JiEDQKyzcaDDQLQzfKVCgLi0PKVCgKwgbuWDQK4qIuIDAKDhrjXCAKT%2B%2B00AqGSlqELAoPh28wDAvSit9QCAsvep4YKAtj71VwC9pD07goC8rfjvgoCoryYqAECv6uC5A4C2dmTnQUCrdnKtgICyJiTrwsCjLGlBQKNsaUFAo6xpQUCj7GlBQKIsaUFAomxpQUCirGlBQKbsaUFApSxpQUCjLHlBgKMsekGAoyx7QYCjLHRBgKMsdUGAoyx2QYCjLHdBgKMscEGAoyxhQUCjLGJBQKNseUGAo2x6QYCjbHtBgKNsdEGAo2x1QYCjbHZBgKNsd0GAo2xwQYCjbGFBQKNsYkFAo6x5QYCjrHpBgLopM%2F9CwLsyZauAQL4oO3lBAK8yuqBCwL1hriZBwLUpvv7CALsqKmSDgLqoY%2BHAwLCi9reA5HII3R9bARNVKmrB9WBnfeJepHFJrdPAtcLnXlE%2BdKP&username2=gfk7ljlyks&password=boolbool1&password2=boolbool1&email=myeail%40gf.com&fname=&lname=&phone=&street=&city=&BYear=&Bmonth=%D7%99%D7%A0%D7%95%D7%90%D7%A8&Bday=1&career=&signature=&homepage=&icq=&Morehobbies=&allowmail=on&SendNews=on&chkterms=on&btnSubmit=%D7%9C%D7%97%D7%A5+%D7%9C%D7%A1%D7%99%D7%95%D7%9D+%D7%94%D7%94%D7%A8%D7%A9%D7%9E%D7%94+%D7%9C%D7%90%D7%AA%D7%A8
but as I see in the documentation, the only option is to add the data as a dict (which wouldn't work with that data for some reason)
Anyone has an idea how to send this data properly? (should result a 302)
or even better, anyone knows how to turn this data in to a dict ?
There's no issue sending raw post data:
raw_data = '__VIEWSTATE=%2FwEPDwUJODgwODc4MzI2D2QWBAIEDxYCHgdWaXNpYmxlaGQCBg8WAh8AZxYCZg9kFhBmDw8WAh4EVGV4dAUl16jXmdep15XXnSDXntep16rXntepINeX15PXqSDXnNeQ16rXqGRkAgEPFgIeBWNsYXNzBSNmb3JtLWdyb3VwIGhhcy1mZWVkYmFjayBoYXMtc3VjY2VzcxYIAgEPDxYCHwEFLSog16nXnSDXntep16rXntepICjXkdeZ158gNCDXnCAxMiDXqteV15nXnSkgOmRkAgUPDxYCHwBoZGQCBw8PFgQeCENzc0NsYXNzZR4EXyFTQgICFgIfAgUwZ2x5cGhpY29uIGZvcm0tY29udHJvbC1mZWVkYmFjayBnbHlwaGljb24tcmVtb3ZlZAIJDxYGHwIFE2FsZXJ0IGFsZXJ0LXN1Y2Nlc3MeBXN0eWxlBQ5kaXNwbGF5OmJsb2NrOx4JaW5uZXJodG1sBRjXqdedINee16nXqtee16kg16TXoNeV15lkAgIPFgIfAGgWAmYPFgIfAgUXZm9ybS1ncm91cCBoYXMtZmVlZGJhY2sWBAIDDw8WBB8DZR8EAgJkZAIFDxYCHwUFDWRpc3BsYXk6bm9uZTtkAgMPFgIfAgUXZm9ybS1ncm91cCBoYXMtZmVlZGJhY2sWBgIBDw8WAh8AaGRkAgUPDxYEHwNlHwQCAmRkAgcPFgIfBQUNZGlzcGxheTpub25lO2QCBA8WAh8CBRdmb3JtLWdyb3VwIGhhcy1mZWVkYmFjaxYEAgMPDxYEHwNlHwQCAmRkAgUPFgIfBQUNZGlzcGxheTpub25lO2QCBQ8WAh8CBRdmb3JtLWdyb3VwIGhhcy1mZWVkYmFjaxYEAgMPDxYEHwNlHwQCAmRkAgUPFgIfBQUNZGlzcGxheTpub25lO2QCEw8WAh8CBRdmb3JtLWdyb3VwIGhhcy1mZWVkYmFjaxYEAgUPD2QWAh8FBQ1kaXNwbGF5Om5vbmU7ZAIHDw8WBB8DZR8EAgJkZAIXDxYGHwIFEmFsZXJ0IGFsZXJ0LWRhbmdlch8FBQ5kaXNwbGF5OmJsb2NrOx8GBSjXl9eV15HXlCDXnNeQ16nXqCDXkNeqINeq16DXkNeZINeU15DXqteoZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAwUJYWxsb3dtYWlsBQhTZW5kTmV3cwUIY2hrdGVybXNHWETH5Z00Bw%2FRQ%2BPP7XKuKE1Yc7MfMt6j3NmJGEldOg%3D%3D&__VIEWSTATEGENERATOR=98F5786E&__EVENTVALIDATION=%2FwEWPwLc4fuhDgLPv6LBCALyveCRDwKt9JiEDQKyzcaDDQLQzfKVCgLi0PKVCgKwgbuWDQK4qIuIDAKDhrjXCAKT%2B%2B00AqGSlqELAoPh28wDAvSit9QCAsvep4YKAtj71VwC9pD07goC8rfjvgoCoryYqAECv6uC5A4C2dmTnQUCrdnKtgICyJiTrwsCjLGlBQKNsaUFAo6xpQUCj7GlBQKIsaUFAomxpQUCirGlBQKbsaUFApSxpQUCjLHlBgKMsekGAoyx7QYCjLHRBgKMsdUGAoyx2QYCjLHdBgKMscEGAoyxhQUCjLGJBQKNseUGAo2x6QYCjbHtBgKNsdEGAo2x1QYCjbHZBgKNsd0GAo2xwQYCjbGFBQKNsYkFAo6x5QYCjrHpBgLopM%2F9CwLsyZauAQL4oO3lBAK8yuqBCwL1hriZBwLUpvv7CALsqKmSDgLqoY%2BHAwLCi9reA5HII3R9bARNVKmrB9WBnfeJepHFJrdPAtcLnXlE%2BdKP&username2=gfk7ljlyks&password=boolbool1&password2=boolbool1&email=myeail%40gf.com&fname=&lname=&phone=&street=&city=&BYear=&Bmonth=%D7%99%D7%A0%D7%95%D7%90%D7%A8&Bday=1&career=&signature=&homepage=&icq=&Morehobbies=&allowmail=on&SendNews=on&chkterms=on&btnSubmit=%D7%9C%D7%97%D7%A5+%D7%9C%D7%A1%D7%99%D7%95%D7%9D+%D7%94%D7%94%D7%A8%D7%A9%D7%9E%D7%94+%D7%9C%D7%90%D7%AA%D7%A8'
requests.post(url, data=raw_data)
A minor bonus is that your data is already percent encoded.
From the doc string:
post(url, data=None, json=None, **kwargs)
Sends a POST request.
:param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
:param json: (optional) json data to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
So data can be a dictionary, string/bytes, or a file-like object.
Perhaps you need to specify the Content-Type header like this:
requests.post(url, data=raw_data, headers={'Content-Type': 'application/x-www-form-urlencoded'})
you can geenrate the code form postman itself in postman:
To send from python POST request:
def send_data(*args):
import requests
from datetime import datetime
try:
headers = {
'HodHodApiKey': args[5],
'Content-Type': 'application/json'}
timeDate = args[2].strftime("%Y-%m-%dT%H:%M:%SZ")
# print("Inside API::", timeDate)
payload = '{\"cameraId\":"'+str(args[0])+'",\"picture\": "'+str(args[1])+'",\"timeDate\":"'+str(timeDate)+'",\"voilationName\": "'+str(args[3])+'"\r\n\t}'
result = requests.post(args[4],data=payload,headers=headers)
print("Result: ", result)
lJsonResult = result.json()
print("lJsonResult", lJsonResult)
# print(result.status_code)
if result.status_code == 201:
print(" Added DataName.. ")
except Exception as e:
print("Failed to send New data to server....", e)

Using requests to send byte-array to webservice using http post

Currently I'm trying to send a byte-array to a webservice, but i get the error message, that a bytearray is not serializeable:
TypeError: bytearray(b'') is not JSON serializable
I'm using the following code
Sending the requests
# Set blob
with open('demo-file.txt') as file:
f = file.read()
b = bytearray(f)
print a.set_data('5cb9bc4d-c0fd-40ab-8b74-4e62b50d8966', b)
Set_Data method:
def set_data(self, path, data):
"""
Save data in
Parameter
--------
path (str): Path as string
data (bytearray): Data as bytearray
"""
result = requests.post(self.url + '/set', json = { 'path': path, 'data': data})
# Check status and token
if result.status_code == 200:
return result.text
What am I doing wrong, do I have to use some other methods for sending bytearrays?
Thank you all a lot!
If you really need json, you have to encode your binary data. See: Base64 encoding in Python 3
An alternative: How to send binary post data via HTTP?

ValueError: Data must not be a string

I am trying to do the following with requests:
data = {'hello', 'goodbye'}
json_data = json.dumps(data)
headers = {
'Access-Key': self.api_key,
'Access-Signature': signature,
'Access-Nonce': nonce,
'Content-Type': 'application/json',
'Accept': 'text/plain'
}
r = requests.post(url, headers=headers, data=json_data,
files={'file': open('/Users/david/Desktop/a.png', 'rb')})
However, I get the following error:
ValueError: Data must not be a string.
Note that if I remove the files parameter, it works as needed. Why won't requests allow me to send a json-encoded string for data if files is included?
Note that if I change data to be just the normal python dictionary (and not a json-encoded string), the above works. So it seems that the issue is that if files is not json-encoded, then data cannot be json-encoded. However, I need to have my data encoded to match a hash signature that's being created by the API.
When you specify your body to a JSON string, you can no longer attach a file since file uploading requires the MIME type multipart/form-data.
You have two options:
Encapsulate your JSON string as part as the form data (something like json => json.dumps(data))
Encode your file in Base64 and transmit it in the JSON request body. This looks like a lot of work though.
1.Just remove the line
json_data = json.dumps(data)
and change in request as data=data.
2.Remove 'Content-Type': 'application/json' inside headers.
This worked for me.
Alternative solution to this problem is to post data as file.
You can post strings as files. Read more here:
http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file
Here is explained how to post multiple files:
http://docs.python-requests.org/en/latest/user/advanced/#post-multiple-multipart-encoded-files
removing the following helped me in my case:
'Content-Type': 'application/json'
then the data should be passed as dictionary
If your files are small, you could simply convert the binary (image or anything) to base64 string and send that as JSON to the API. That is much simpler and more straight forward than the suggested solutions. The currently accepted answer claims that is a lot of work, but it's really simple.
Client:
with open('/Users/houmie/Downloads/log.zip','rb') as f:
bytes = f.read()
tb = b64encode(bytes)
tb_str = tb.decode('utf-8')
body = {'logfile': tb_str}
r = requests.post('https://prod/feedback', data=json.dumps(body), headers=headers)
API:
def create(event, context):
data = json.loads(event["body"])
if "logfile" in data:
tb_back = data["logfile"].encode('utf-8')
zip_data = base64.b64decode(tb_back)

How do I make a GET request with JSON in the request body

I need to send this JSON array in a GET request
{"user": "jähn", "id": 3}
I tried to use
data = '{"user": "jähn", "id": 3}'
headers = {
'Content-type': 'application/json',
'Accept': 'text/plain'
}
request = urllib.request.Request(self.update_url, data=data,
headers=headers, method='GET')
response = urllib.request.urlopen(request)
But its failing with: TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
Another thing that I find quite weird is that it tells me about POST data although I set the method on the Request to GET.
Since this is a simple script I'd prefer not to use a library like python-requests
You cannot make a GET request with a JSON-encoded body, as a GET request only ever consists of the URL and the headers. Parameters are encoded into the URL using URL encoding instead, there is no option to encode such parameters to JSON instead.
You create URL-encoded parameters with the urllib.parse.urlencode() function, then appended to the URL with ?.
from request.parse import urlencode
data = {"user": "jähn", "id": 3} # note, a Python dictionary, not a JSON string
parameters = urlencode(data)
response = urllib.request.urlopen('?'.join((self.update_url, parameters)))
Do not use the data parameter; using that keyword argument forces a request to use the POST method:
data must be a bytes object specifying additional data to send to the server, or None if no such data is needed. Currently HTTP requests are the only ones that use data; the HTTP request will be a POST instead of a GET when the data parameter is provided. data should be a buffer in the standard application/x-www-form-urlencoded format.

Categories