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

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?

Related

Send JSON file in response to a request, Flask

I have an endpoint which is receiving a text file from a request, which the flask server processes and now need to send a response which should be a json file. I have read and performed the operations of received txt file, and now when I send the dict by jsonify I get this in terminal.
Response 444 bytes [200 OK]
How do I get the json file or is there any other way of sending the JSON file in response? Since I won't be in control of the server that will send the request I need a way to send JSON file.
Code Handling the response
#app.route('/automated_testing', methods=['GET','POST'])
def getfile():
if request.method == 'POST':
for file in request.files:
links = request.files[file].read()
#Since a byte sized object is returned
links = [links.decode('utf8').strip()]
links = links[0].split("\n")
res = dict()
for i in links:
f = FlarePredictor(i)
res[i] = f[0]
print(jsonify(res), file=sys.stderr)
return jsonify(res)
else:
return "GET REQ"
return "Hi"
Code used to send the request
import requests
with open('test.txt', 'rb') as f:
r = requests.post('http://127.0.0.1:5000/automated_testing', files={'test.txt': f})
requests supports JSON out-of-the-box:
json = r.json()
Now json will be a regular Python dictionary containing the data.

Python Flask : Returned file is not readable

While implementing a rest API in python flask, I have used several options to return a file (any type) , read it and save it to local repository of request but encountered with multiple errors as below:
Case 1:
def download_file():
return send_file('any_file.pdf')
r = requests.get(url = 'http://localhost:5000/download').read()
has responded with a error Response object has no attribute read/text/content
Case 2:
def download_file():
file = open('any_file.pdf','r').read()
return file
r = requests.get(url = 'http://localhost:5000/download')
has responded with a error Return doesn't accept this
So How can I do this as flask is not allowing to return a file without response object and response object is not readable and doesn't support to save that file directly.
The Flask server code in Case 1 is correct. A more complete example:
#app.route('/download')
def download_file():
# Some logic here
send_file('any_file.pdf')
However the Response object returned by requests.get doesn't have a read method. The correct way is to use:
Response.content: Content of the response, in bytes.
So, the client code should be:
r = requests.get('http://localhost:5000/download')
bytes = r.content
# Now do something with bytes, for example save it:
with open('downloaded_file.ext', 'wb') as f:
f.write(bytes)

Return multipart/formdata containing png file and markdown as a flask response

Hi I am trying to return multipart from data from a get request. However I am unable to return a MultipartEncoder object as a response. I have attempted the solution at
Can I serve a multipart http response in Flask?
The below code only returns the 'toPersonEmail' field. How does one return m as a response in Flask?
#app.route("/multipart", methods=['GET'])
def send_multipart():
m = MultipartEncoder(fields={ 'markdown': "> Block quotes are written like so in markdown.",
'toPersonEmail':'d#d.com',
'files': ("pnggrad16rgb.png", open("pnggrad16rgb.png", 'rb'),
'image.png')})
return Response(m.fields, mimetype=m.content_type)
Flask has no specific provision for multipart mime responses; multipart/form is a mimetype normally only used in a POST request to the server, not in a response from a HTTP server.
If you must return valid multipart mime data, render the body to bytes and set the right headers on a response object; the `(
m = MultipartEncoder(fields={ 'markdown': "> Block quotes are written like so in markdown.",
'toPersonEmail':'d#d.com',
'files': ("pnggrad16rgb.png", open("pnggrad16rgb.png", 'rb'),
'image.png')})
return (m.to_string(), {'Content-Type': m.content_type})
If you wanted to stream the response, you'd have to supply your own generator function that reads from the multipart encoder in chunks:
def chunked_reader(f, chunksize=2 ** 20): # 1Mb chunks
while True:
chunk = f.read(chunksize)
if not chunk:
return
yield chunk
and use that to wrap your MultipartEncoder() instance when streaming response data:
# include the Content-Length header, even though we are streaming
return Response(
chunked_reader(m), content_type=m.content_type,
headers={'Content-Length': m.len})
The MultipartEncoder() object supports a .read() method just like files do.

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)

I keep getting this error the JSON object must be str, not 'bytes' [duplicate]

I've been trying to update a small Python library called libpynexmo to work with Python 3.
I've been stuck on this function:
def send_request_json(self, request):
url = request
req = urllib.request.Request(url=url)
req.add_header('Accept', 'application/json')
try:
return json.load(urllib.request.urlopen(req))
except ValueError:
return False
When it gets to this, json responds with:
TypeError: the JSON object must be str, not 'bytes'
I read in a few places that for json.load you should pass objects (In this case an HTTPResponse object) with a .read() attached, but it doesn't work on HTTPResponse objects.
I'm at a loss as to where to go with this next, but being that my entire 1500 line script is freshly converted to Python 3, I don't feel like going back to 2.7.
Facing the same problem I solve it using decode()
...
rawreply = connection.getresponse().read()
reply = json.loads(rawreply.decode())
I recently wrote a small function to send Nexmo messages. Unless you need the full functionality of the libpynexmo code, this should do the job for you. And if you want to continue overhauling libpynexmo, just copy this code. The key is utf8 encoding.
If you want to send any other fields with your message, the full documentation for what you can include with a nexmo outbound message is here
Python 3.4 tested Nexmo outbound (JSON):
def nexmo_sendsms(api_key, api_secret, sender, receiver, body):
"""
Sends a message using Nexmo.
:param api_key: Nexmo provided api key
:param api_secret: Nexmo provided secrety key
:param sender: The number used to send the message
:param receiver: The number the message is addressed to
:param body: The message body
:return: Returns the msgid received back from Nexmo after message has been sent.
"""
msg = {
'api_key': api_key,
'api_secret': api_secret,
'from': sender,
'to': receiver,
'text': body
}
nexmo_url = 'https://rest.nexmo.com/sms/json'
data = urllib.parse.urlencode(msg)
binary_data = data.encode('utf8')
req = urllib.request.Request(nexmo_url, binary_data)
response = urllib.request.urlopen(req)
result = json.loads(response.readall().decode('utf-8'))
return result['messages'][0]['message-id']
I met the problem as well and now it pass
import json
import urllib.request as ur
import urllib.parse as par
html = ur.urlopen(url).read()
print(type(html))
data = json.loads(html.decode('utf-8'))
Since you are getting a HTTPResponse, you can use Tornado.escape and its json_decode() to convert the JSON string into a dictionary:
from tornado import escape
body = escape.json_decode(body)
From the manual:
tornado.escape.json_decode(value)
Returns Python objects for the given JSON string.

Categories