I'm trying to make a put request to the local server using the put request using curl:
curl -X PUT -H "Content-Type: application/json" -d '{"connid":"12"}' "127.0.0.1:8000/api/kill"
I receive the same response:
'WSGIRequest' object has no attribute 'PUT'
for the following code:
def kill(req):
conid = req.PUT['connid']
statusres = {}
if conid in state:
error[conid] = 'true'
statusres['status'] = 'ok'
else:
statusres['status'] = 'invalid connection Id : '+ conid
return JsonResponse(statusres)
I also used #csrf_exempt before the function.
You have misunderstood several things here.
When you send form-encoded data, whether it's POST or PUT, in Django you always find the parameters in request.POST. So you would find your data in request.POST['conid'].
However, you are not sending form-encoded data; you are sending JSON. You need to access the request body, and pass it to the json.loads function to decode:
def kill(request):
data = json.loads(request.body)
conid = data['connid']
Related
I'm trying yo pass a Content-Type to a flask app (running on GAE), But from python I cannot get the content type header even though I'm passing it
The server-side handler is the following:
#app.route('/api/handlers',methods=['POST'])
def color_list_post():
if(request.headers['Content-Type']=='application/color'):
logging.info('my-format')
elif(request.headers['Content-Type']=='application/x-www-form-urlencoded'):
logging.info('url-encoded')
else:
logging.info('wrong content-type')
return ""
The header passed is:
application/color
this is my request:
curl -H "Content-Type:application/color" -X POST http://localhost:8080/api/handlers
and this the error I get:
KeyError: 'CONTENT_TYPE'
I get a confused error.
Its about swift data type.
there is my network demo:
func initRequst(HttpType: httpType,content:String,dic:Dictionary<String,Any>){
let data = try! JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
print(data)
switch HttpType {
case .post:
url = URL.init(string: "http://localhost:5000/" + content)
req = NSMutableURLRequest.init(url: url!)
req?.httpMethod = "POST"
req?.httpBody = data
case .get:
url = URL.init(string: "http://localhost:5000/" + content)
req = NSMutableURLRequest.init(url: url!)
req?.httpBody = data
req?.httpMethod = "GET"
}
}
And there is my flask server have received error and demo:
TypeError: 'NoneType' object is not subscriptable
#app.route('/userLogin',methods=["GET"])
def userLogin():
get_username = request.json['username']
get_password = request.json['password']
return jsonify({"uerId":databasePort.checkUserInformation(get_username,get_password)})
it seems that swift data sending type have not be identified.How to fix it? Thanks!
You could try setting the Content-Type header to application/json before sending the request in Swift. Then Flask will attempt to decode it and assign it to the request's json attribute:
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
Flask will set request.json only if the incoming request sets the content type to json, otherwise it will assume form encoded data which it will assign to request.form.
For example I tried that command via terminal:
curl -F "profileImage=#/home/user/image.jpg" -F "{'firstName':'hello'};type=application/json" http://127.0.0.1:8000/api/v1/signup/
Then I received the request object like that:
print request.FILES
# <MultiValueDict: {u'profileImage': [<InMemoryUploadedFile: image.jpg (image/jpeg)>]}>
print request.DATA
# <QueryDict: {u"{'firstName':'hello'};content-type": [u'application/json']}>
The image is ok, but QueryDict is not represented correctly - all JSON file is a key and content-type
is a value.
In Django use these parsers:
parser_classes = (MultiPartParser, FormParser, JSONParser,)
I necessary need to send text data via JSON structure .
If you want to POST with multipart/form-data content-type, you can't also specify application/json. The simple fix for this is to send the form data in url-encoded format. Try this command:
curl -F "profileImage=#/home/user/image.jpg" -F "firstName=hello" http://127.0.0.1:8000/api/v1/signup/
I came up with a solution like this:
class MultiPartJSONParser(parsers.MultiPartParser):
def parse(self, stream, media_type=None, parser_context=None):
dataAndFiles = super(MultiPartJSONParser, self).parse(stream, media_type, parser_context)
try:
jsonData = json.loads(dataAndFiles.data.get('data'))
except ValueError as exc:
raise parsers.ParseError('JSON parse error - %s' % six.text_type(exc))
# make data mutable, insert json data, and remove raw data
dataAndFiles.data = data = dataAndFiles.data.copy()
data.update(jsonData)
del data['data']
return dataAndFiles
It assumes that the JSON part is sent as a form field called 'data'.
If you want to get really slick, you could probably parse the data field according to the media type value of the Accept header. Alternatively, you could POST the data as a file and parse according to its content type.
Note that to use this parser class, you'll need to set the following default settings:
REST_FRAMEWORK = {
'FORM_METHOD_OVERRIDE': None,
'FORM_CONTENT_OVERRIDE': None,
}
That is due to this bug: https://github.com/tomchristie/django-rest-framework/issues/1346
the parameter to specify the content-type is just "type="
curl -F "profileImage=#/home/user/image.jpg" -F "{'firstName':'hello'};type=application/json" http://127.0.0.1:8000/api/v1/signup/
However, I don't think that will allow the JSONParser to take the information..., but you can try :)
Here :-
curl -vvv -X POST -H "Content-Type:multipart/form-data" -H "Accept:application/json" -H -F "username=sample" -F "password=something" -F "image=#Mercury.gif" http://127.0.0.1:8000/api/objects
No need to type accepts application/json. Django will automatically treat these as dictionary objects.
Print request.DATA and request.FILES will give you
<QueryDict: {u'username': [u'sample'] , u'password': [u'something']}>
<MultiValueDict: {u'image': [<InMemoryUploadedFile: Mercury.gif (image/gif)>]}>
Thanks xjtian - link that you pasted in comment + some researches make solution.
So:
If you want sending json data + file - send two requests. First will create object on backend and give id to app. Second will update object with file using gived id. More info there.
If you don't care about data types - send request via "multipart/form-data".
Thanks to all for answers, you realy helps, but I think this one is more appropriate for REST architecture.
My understanding is that request.args in Flask contains the URL encoded parameters from a GET request while request.form contains POST data. What I'm having a hard time grasping is why when sending a POST request, trying to access the data with request.form returns a 400 error but when I try to access it with request.args it seems to work fine.
I have tried sending the request with both Postman and curl and the results are identical.
curl -X POST -d {"name":"Joe"} http://127.0.0.1:8080/testpoint --header "Content-Type:application/json"
Code:
#app.route('/testpoint', methods = ['POST'])
def testpoint():
name = request.args.get('name', '')
return jsonify(name = name)
You are POST-ing JSON, neither request.args nor request.form will work.
request.form works only if you POST data with the right content types; form data is either POSTed with the application/x-www-form-urlencoded or multipart/form-data encodings.
When you use application/json, you are no longer POSTing form data. Use request.get_json() to access JSON POST data instead:
#app.route('/testpoint', methods = ['POST'])
def testpoint():
name = request.get_json().get('name', '')
return jsonify(name = name)
As you state, request.args only ever contains values included in the request query string, the optional part of a URL after the ? question mark. Since it’s part of the URL, it is independent from the POST request body.
Your json data in curl is wrong, so Flask does not parse data to form.
Send data like this: '{"name":"Joe"}'
curl -X POST -d '{"name":"Joe"}' http://example.com:8080/testpoint --header "Content-Type:application/json"
just change args for form and it will work
#app.route('/testpoint', methods = ['POST'])
def testpoint():
name = request.form.get('name', '')`enter code here`
return jsonify(name = name)
I'm having a difficulty trying to make a Python REST POST to a webservice running on Glassfish. I have verified that POST works ok using CURL but having no luck with Python.
Here is the CURL request that works ok.
curl -X POST -H "Content-Type: application/json" -d '{"id":1,"lastname":"smith"}'
http://192.168.0.20:8080/field1/resources/com.field1entity.field1
Here is the Python code to make the POST request
import urllib
import httplib2
def call():
http = httplib2.Http()
url = 'http://192.168.0.20:8080/field1/resources/com.field1entity.field1'
params = urllib.urlencode({"id":11111,"lastname":"oojamalip"})
response, content = http.request(url, 'POST', params, headers={'Content-type':'application/json'})
print "lets stop here to have a looksy at the variables"
print content
if __name__ == '__main__':
namesPage = call()
print namesPage
Output from console,
Unexpected character ('l' (code 108)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: org.apache.catalina.connector.CoyoteInputStream#18f494d; line: 1, column: 2]
Hope someone can shed some light on the problem.
thanks
Nick
You are url encoding the prams and then telling the server it is json encoded
import json
params = json.dumps({"id":11111,"lastname":"oojamalip"})
# then
response, content = http.request(url, 'POST', body=params, headers={'Content-type':'application/json'})