I have this below soap envelope where I have send string array.
<apiKey xsi:type="xsd:string">Ab12-Ab12-Ab12-Ab12</apiKey>§
<baseScheduleRollout xsi:type="flex:baseScheduleRollout" xmlns:flex="http://app.quinyx.com/soap/FlexForce">
<badgeNos xsi:type="flex:ArrayOfString" soapenc:arrayType="xsd:string[]">
<item1>1022</item1>
<item2>1030</item2>
<item2>10112330</item2>
</badgeNos>
<fromDateTime xsi:type="xsd:dateTime">2020-11-05T00:00:00</fromDateTime>
<toDateTime xsi:type="xsd:dateTime">2020-11-24T00:00:00</toDateTime>
I know how to send a soap request and my complextype is okay. But I think my string array passing system is wrong. Though I tried to use anyObject but still not working
from zeep import Client
from zeep import xsd
import datetime
from requests import Session
from requests.auth import HTTPBasicAuth
from zeep.transports import Transport
wsdl = "https://api.quinyx.com/FlexForceWebServices.php?wsdl"
session = Session()
session.auth = HTTPBasicAuth('username', 'password')
client = Client(wsdl, transport=Transport(session=session))
ArrayOfString = client.get_element('ns0:ArrayOfObject')
badgeNo = ArrayOfString(['146223'])
data = { "apiKey" : "apikey" ,
"baseScheduleRollout" :{
"badgeNos":badgeNo,
"fromDateTime":xsd.SkipValue,
"toDateTime":xsd.SkipValue
}
}
result = client.service.wsdlGetBaseScheduleRolledoutHours(**data)
result
Error
LookupError: No element 'ArrayOfObject' in namespace https://api.quinyx.com/soap/FlexForce. Available elements are: -
I am trying to send a compressed numpy array (compressed with zlib) to the flask server with post request, but the compressed bytes object is getting changed in the server end. How to properly send the bytes object with requests post request so that I can decompress on the server end?
server.py
from flask import Flask
from flask_restful import Resource, Api, reqparse
import json
import numpy as np
import base64
# compression
import zlib
app = Flask(__name__)
api = Api(app)
parser = reqparse.RequestParser()
parser.add_argument('imgb64')
class Predict(Resource):
def post(self):
data = parser.parse_args()
if data['imgb64'] == "":
return {
'data':'',
'message':'No file found',
'status':'error'
}
img = data['imgb64']
print('rec')
# decompress
print(type(img))
print(img)
dec = zlib.decompress(img) # this gives me error
if img:
pass
return json.dumps({
'data': 'done',
'message':'darknet processed',
'status':'success'
})
return {
'data':'',
'message':'Something when wrong',
'status':'error'
}
api.add_resource(Predict,'/predict')
if __name__ == '__main__':
app.run(debug=True, host = '0.0.0.0', port = 5000, threaded=True)
client.py
import numpy as np
import base64
import zlib
import requests
frame = np.random.randint(0,255,(5,5,3)) # dummy rgb image
# compress
data = zlib.compress(frame)
print('b64 encoded')
print(data)
print(len(data))
print(type(data))
r = requests.post("http://127.0.0.1:5000/predict", data={'imgb64' : data}) # sending compressed numpy array
This gives me the following error:
TypeError: a bytes-like object is required, not 'str'
So, I tried to convert the string to bytes object:
dec = zlib.decompress(img.encode()) # this gives me error
But, this one also gives me an error:
zlib.error: Error -3 while decompressing data: incorrect header check
I tried with other encodings, they also failed.
One thing I noticed is, when I print the compressed bytes in the client end, it reads:
b'x\x9c-\xcf?J\x82q\x00\x06\xe0\x0ftrVP\\C\xf4\x06\x9268\t\xcdR\x8ej.F\xa0\xe0\xd0\xa6\xa3\xe0V\x07\x10\x1cL\xc8\xd1\x03\xd4\xe4\t\x0c\x12\x84\xb6D\x0c#\xbc\x80O\xf0\x1b\x9e\xf5\xfdS\x89\xa2h\xcf\x9a\x03\xef\xc4\xf8cF\x92\r\xbf4i\x11g\xc83\x0f\x8c\xb9\xa2#\x8e\x1bn\xd91g\xc0\x91%\xd7\xdc\xf3M\x83<i:L\xa8\xf1\x19\xfa\xffw\xfd\xf0\xc5\x94:O\x9cH\x85\xcc6#\x1e\xc3\xf6\x05\xe5\xa0\xc7\x96\x04]J\\\x90\xa1\x1f~Ty\xe1\x8d\x15w|P\xe4\x95K\xb2!\xe3\x0cw)%I'
But on the server end, the received string is completely different:
�4ig�3���#�n�1g��%���M�<i:L����w��Ŕ:O�H��6#���ǖ]J\��~Ty�w|P�K�!�w)%I
I also tried to send the bytes as string, by
r = requests.post("http://127.0.0.1:5000/predict", data={'imgb64' : str(data)})
But, I can't decompress the data on the server end.
It seems, I can't send the zlib compressed bytes directly, so I used base64 to encode the data into ascii string.
So, in summary this worked for me, numpy array/any non-string data -> zlib compression -> base64 encode -> post request -> flask -> base64 decode -> zlib decompress
client.py
import numpy as np
import base64
import zlib
import requests
frame = np.random.randint(0,255,(5,5,3)) # dummy rgb image
# compress
data = zlib.compress(frame)
data = base64.b64encode(data)
data_send = data
data2 = base64.b64decode(data)
data2 = zlib.decompress(data2)
fdata = np.frombuffer(data2, dtype=np.uint8)
print(fdata)
r = requests.post("http://127.0.0.1:5000/predict", data={'imgb64' : data_send})
server.py
from flask import Flask
from flask_restful import Resource, Api, reqparse
import json
import numpy as np
import base64
# compression
import zlib
import codecs
app = Flask(__name__)
api = Api(app)
parser = reqparse.RequestParser()
parser.add_argument('imgb64', help = 'type error')
class Predict(Resource):
def post(self):
data = parser.parse_args()
#print(data)
if data['imgb64'] == "":
return {
'data':'',
'message':'No file found',
'status':'error'
}
#img = open(data['imgb64'], 'r').read() # doesn't work
img = data['imgb64']
data2 = img.encode()
data2 = base64.b64decode(data2)
data2 = zlib.decompress(data2)
fdata = np.frombuffer(data2, dtype=np.uint8)
print(fdata)
if img:
return json.dumps({
'data': 'done',
'message':'darknet processed',
'status':'success'
})
return {
'data':'',
'message':'Something when wrong',
'status':'error'
}
api.add_resource(Predict,'/predict')
if __name__ == '__main__':
app.run(debug=True, host = '0.0.0.0', port = 5000, threaded=True)
I found, that sending JSON, which has entry which starts with "function" produces invalid JSON.
Example:
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import groovyx.net.http.RESTClient
import static groovyx.net.http.ContentType.JSON
def jsonSlurper = new JsonSlurper()
// if you replace `function` on next line to any other word - it will work correctly
String baseContextJSON = '{ "afterResponse": "function (getParam, setParam, genInfo) { }" }'
def baseContext = jsonSlurper.parseText(baseContextJSON)
println JsonOutput.prettyPrint(JsonOutput.toJson(baseContext))
RESTClient http = new RESTClient('https://requestinspector.com')
http.post(
path: "/inspect/01dh7rs82be884ke89jcny061e",
body: baseContext, // if I use baseContextJSON here - correct JSON would be sent
query: null,
requestContentType: JSON
)
This code sends this payload:
{"afterResponse":function(getParam,setParam,genInfo){}}
That's invalid JSON - note missing quote around function.
You can see actual received payloads at https://requestinspector.com/p/01dh7rs82be884ke89jcny061e (until it expires, or you can generate you own)
I can't even figure out:
- is it bug in HTTPBuilder?
- is it bug in how Groovy handles and convert Map to JSON?
Any idea what can I do to pin root cause?
I am trying to learn some Http Server in an udacity online academy. The thing is that the folllowing code is triggering the error Message: Unsupported method ('POST'). Error 501 Python:
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import parse_qs
class MessageHandler(BaseHTTPRequestHandler):
def do_POST(self):
# 1. How long was the message?
length = int(self.headers.get('Content-length', 0))
# 2. Read the correct amount of data from the request.
data = self.rfile.read(length).decode()
# 3. Extract the "message" field from the request data.
message = parse_qs(data)["message"][0]
# Send the "message" field back as the response.
self.send_response(200)
self.send_header('Content-type', 'text/plain; charset=utf-8')
self.end_headers()
self.wfile.write(message.encode())
if __name__ == '__main__':
server_address = ('', 8000)
httpd = HTTPServer(server_address, MessageHandler)
httpd.serve_forever()
Which Python? Your code is correct. Tested it right now, it sends the response.
The only modification I've made is
#message = parse_qs(data)["message"][0]
message = 'hello'
Client code:
import requests
res = requests.post('http://localhost:8000/abc', data = {'key':'value'})
print(res)
Client gets 200 response
Here is the related code
import logging
logging.getLogger('googleapicliet.discovery_cache').setLevel(logging.ERROR)
import datetime
import json
from flask import Flask, render_template, request
from flask import make_response
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from oauth2client.client import AccessTokenCredentials
...
#app.route('/callback_download')
def userselectioncallback_with_drive_api():
"""
Need to make it a background process
"""
logging.info("In download callback...")
code = request.args.get('code')
fileId = request.args.get('fileId')
logging.info("code %s", code)
logging.info("fileId %s", fileId)
credentials = AccessTokenCredentials(
code,
'flex-env/1.0')
http = httplib2.Http()
http_auth = credentials.authorize(http)
# Exports a Google Doc to the requested MIME type and returns the exported content. Please note that the exported content is limited to 10MB.
# v3 does not work? over quota?
drive_service = build('drive', 'v3', http=http_auth)
drive_request = drive_service.files().export(
fileId=fileId,
mimeType='application/pdf')
b = bytes()
fh = io.BytesIO(b)
downloader = MediaIoBaseDownload(fh, drive_request)
done = False
try:
while done is False:
status, done = downloader.next_chunk()
logging.log("Download %d%%.", int(status.progress() * 100))
except Exception as err:
logging.error(err)
logging.error(err.__class__)
response = make_response(fh.getbuffer())
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = \
'inline; filename=%s.pdf' % 'yourfilename'
return response
It is based on some code example of drive api. I am trying to export some files from google drive to pdf format.
The exception comes from the line
response = make_response(fh.getbuffer())
It throws the exception:
TypeError: 'memoryview' object is not callable
How can I retrieve the pdf content properly from the fh? Do I need to further apply some base 64 encoding?
My local runtime is python 3.4.3
I have used an incorrect API. I should do this instead:
response = make_response(fh.getvalue())