python3.5 aiohttp, request post, json format and 405 errors - javascript

I finally sign up because I have no more idea for my problem.
I use asyncio and aiohttp for my back-end part and javascript for the front-end part. But I stuck with a 405 error. (I precise I am a beginner with theses libraries)
I wish retrieve a json from a post request. Here the javascript function:
function postJson (data){
$.ajax({
url : 'http://localhost:8080/postJson',
type : 'POST',
dataType : 'json',
contentType : 'application/json',
data : data, //data are ready at json format, I do not think I need to use JSON.stringify ? I does not change anything to the error anywhere
success : function(code_html, statut){
console.log("success POST");
},
error : function(resultat, statut, erreur){
console.log("error POST");
}
});
}
and the python code:
async def postJson(request):
data = await request.post()
#some code
return Response()
#asyncio.coroutine
def init(loop):
app = Application(loop=loop)
app.router.add_route('POST', '/postJson', postJson)
handler = app.make_handler()
srv = yield from loop.create_server(handler, '127.0.0.1', 8080)
print("Server started at http://127.0.0.1:8080")
return srv, handler
loop = asyncio.get_event_loop()
srv, handler = loop.run_until_complete(init(loop))
try:
loop.run_forever()
except KeyboardInterrupt:
loop.run_until_complete(handler.finish_connections())
With this code I get a 405 error. Here a bite of what says firebug about the request:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 // so json is not in the list.
however, if I take back the line contentType : 'application/json' in my javascript file, it works (but the request send a object called MultiDictProxy and I don't understand how to use the function json() from aiohttp.web package (here).
I really need to get a json object. Someone could help me?

I find the solution. I post the conclusion here for people who could be interested:
python side:
replace the line app.router.add_route('POST', '/postJson', postConf) by
app.router.add_route('POST', '/postJson', postConf, expect_handler = aiohttp.web.Request.json)
in the postJson method:
replace data = await request.post() by data = await request.json()
and on javascript side:
data : JSON.stringify(data)
with this, my method works.

Your example works fine except two things:
#asyncio.coroutine and async with are mutually exclusive
postJson() must return response instance, not None

Related

converting string.json() to javascript

So I want to convert a python script to javascript. The script features a post request, which is supposed to send only a string. I found somewhere that stringname.json() somehow works(which it does), but I am not sure how it works. How do I replicate this in javascript?
Code:
user_info = requests.post('url',
headers=headers,
json = username.json()
Edit: This was a dumb question, ignore this
fetch returns a Promise, so you need to either await it in an async function or use .then
const userInfo = await fetch('url', {
method: "POST",
headers: headers,
body: JSON.stringify(username),
}

Problem Posting json data to API using Axios in Vue JS

I am trying to create a Axios request where i will post json data. The format of the data will be
{"qBody":"aaa","qAnswer":"bbb","qOptions":[],"qType":"GAP","qClass":6,"qSubject":1,"qChapter":1,"qCreatorid":1,"qCreatorrole":"admin"}
But it is posting as
{"data":{"qBody":"aaa","qAnswer":"bbb","qOptions":[],"qType":"GAP","qClass":6,"qSubject":1,"qChapter":1,"qCreatorid":1,"qCreatorrole":"admin"}}
Here is my code snippet:
var data = {
"qBody" : question,
"qAnswer" : trueFalseAnswer,
"qOptions" : qOptions,
"qType" : questionCategory,
"qClass" : className,
"qSubject" : subjectName,
"qChapter" : chapterName,
"qCreatorid" : qCreatorid,
"qCreatorrole" : qCreatorrole
};
const newData = JSON.stringify(data)
this.$axios.post("http://128.199.192.87:8081/api/v1/questions/add",{
newData
},{
'Content-Type': "application/json"
}).then((response)=>{
console.log(response)
})
How can I make the format correct? Thanks in advance
What you are console.log()-ing is not what you're sending. It is the response that's getting back from the server. If you want to log what you're sending, use:
console.log(newData);
... just before making the POST request.
Most likely, you don't need to stringify the request.
What you're seeing in the console is the server response. According to the response-schema in their documentation, the server's response data is placed in the .data property of the response object.
So, apparently, the server sends back the same data. With most servers, this means no error has occurred.
In fewer words, you are not sending your data wrapped as { data: ... }. If you were, you would be getting back: { data: { data: ... } }

Getting None values for POST request (via the Axios library) sent to Python/Django

I am building a web app with Django/Python and trying to send data to a controller via a POST request using the Axios library (within Vue.js code).
The POST QueryDict seems to be empty and I can't see why that is happening:
changeCountry: function(e, id){
console.log("Let's change the country")
console.log(e.target.value) // is printing correctly
console.log(id) // also printing correctly
axios({
method: 'post',
url: '/template/country',
data: {
id: id,
country: e.target.value
},
headers: {
'X-CSRFToken': "{{csrf_token}}"
}
})
.then(function (response) {
alert(response.data); // this is returning what I expect
})
.catch(function (error) {
console.log(error);
})
},
The Python method looks like this:
def update_template_country(request):
pprint(request.POST) # prints an empty QueryDict
id = request.POST.get('id')
country = request.POST.get('country')
print(id, country) #prints None None
return HttpResponse("The country is changed") # this is being returned back to the client
The console.log messages at the top print what I expect and since there is no error I am assuming the CSRF header token is fine. Have I missed something obvious or misunderstood how this is working?
EDIT: looking at the Chrome Network tab, it seems the data is being 'POSTed' correctly:
It shows this:
{"id":"593ff2270098e6e8d3292b60","country":"US"}
and that's what I expect, so I suspect the issue is with Django. But I can't see what that might be.
Write your python POST request like this:
def update_template_country(request):
data = json.loads(request.body)
id = data["id"]
country = data["country"]
'''Any other function you want to perform'''
return HttpResponse(json.dumps({'message':'The country is changed'},status=200)
Basically the problem is with the format of POST request, Django is not able to parse it properly that's why when you print the POST request it return an empty dictionary.

Angular HTTP GET request returns undefined while working in browser

I'am learning AngularJs and I've tried to write a very basic script sending an http request to Ebay public API, I've signed up and got my API keys, I've read the docs several times and wrote this basic code :
$scope.getQueryUrl = function () {
// Some unrelated code ...
$scope.queryUrl["Ebay"] = "http://svcs.sandbox.ebay.com/services/search/FindingService/v1?OPERATION-NAME=findItemsByKeywords&SERVICE-NAME=FindingService&SERVICE-VERSION=1.0.0&GLOBAL-ID=EBAY-US&SECURITY-APPNAME="+dataAuth.EbayKeyApi+"&RESPONSE-DATA-FORMAT=XML&keywords="+$scope.qtext ;
};
$scope.sendRequest = function () {
$scope.getQueryUrl(); // Gets the query url after adding all the parameters
alert($scope.queryUrl.Ebay);
$http.get($scope.queryUrl["Ebay"]).then(
function(response){
alert("success" + response.data );
},
function(response){
alert("error" + response.statusCode );
});
};
How this code should work :
It should create a formated Ebay query url, send it through HTTP GET request and sending back the response .
Note : $scope.qtext & dataAuth.EbayKeyApi are already assigned with their respective values .
What's the problem:
The problem is that using this Angularjs script, the code doesn't work, the alert "Error" is shown, and the response.statusCode is undefined .
But when I copy the formatted Ebay query link in Firefox it works perfectly and the XML response is shown .
The formatted Ebay query was generated using the script provided .
I think it's a header related problem .
$http has some default headers defined. $http sends Json payload and accepts Json as the response by default. Since you are dealing with XML you have to explicitly specify the accepted response type as XML using the header:
Accept: application/xml
Please use the following function with appropriate headers and you should get the response. Also, please look into any Cross Origin Resource Sharing (CORS) restrictions on the ebay API.
function getRequest(url) {
$http({
method: "GET",
url: url,
headers: {
'Content-Type': 'application/xml, text/xml',
'Accept': 'application/xml, text/plain, * / *'
}
})
.then(function (response) {
alert(response.data);
},
function (error) {
alert (error);
});
}
Thank you,
Soma.

Flask - Getting POST data from Angular $http.post()

In a very basic test web app I am making, I am using angular to run a function when a form is submitted. The function asynchronously posts data to a simple api I built which is supposed to input data into a database dependent on the POST information it receives. It seems like the POST is working correctly on the front end, however I cannot access request.json from Flask at all or get any of the post data. I feel like this problem may be something simple I have overlooked but as of now I cannot figure it out at all. Here is some of the code:
AngularJS:
$scope.submitAddMsg = function (){
var data = {'author': $scope.msgauthor, 'message': $scope.msgmsg};
$http.post('/addMessage', data, {headers: {'Content-Type': 'application/json'}}).
success(function(data, status, headers, config) {
console.log(data);
console.log(status);
console.log(headers);
console.log(config);
}).
error(function(data, status, headers, config) {
alert(JSON.parse(data));
});
};
Flask view function for /addMessage
#app.route('/addMessage', methods=['POST'])
def addMessage():
#results in 'None type not iterable'
#response = request.form.get('author')
#results in a 400 error
#response = request.get_json()
#results in a 400 error
#response = request.get_json()
#results in 'author' not defined
#name = request.args.get('author')
#return jsonify(author = author)
return str(jsonify(response))
I cannot stop getting errors as if the request is not what I think it should be, is there something else I should be doing to properly handle this? Because I cannot access any POST information when using Angular to send the POST or even a REST Client with payload exactly how the angular is sending data.
Here is the JavaScript console to see what data, status, headers, and config ends up being in the success function that runs after the POST:
<Response 46 bytes [200 OK]>
testbase.js:53 200
testbase.js:54 function (c){a||(a=Xc(b));return c?(c=a[z(c)],void 0===c&& (c=null),c):a}
testbase.js:55 Object {method: "POST", transformRequest: Array[1], transformResponse: Array[1], headers: Object, url: "/addMessage"…}data: Objectheaders: ObjectAccept: "application/json, text/plain, */*"Content-Type: "application/json"__proto__: Objectmethod: "POST"transformRequest: Array[1]transformResponse: Array[1]url: "/addMessage"__proto__: Object
Any help on getting this working right is much appreciated, let me know if you need more information
you can use request.data to get the raw post data.
you can also set the silent Flag of get_json to True so you can get the exact message of failure.
from the docs
get_json(force=False, silent=False, cache=True)
Parameters:
force – if set to True the mimetype is ignored.
silent – if set to False this method will fail silently and return False.
cache – if set to True the parsed JSON data is remembered on the request.
Try adding app.debug = True before you start the app and try again.
You can also try:
message = request.json.get('message')
And I would also try putting this in your route
['POST', 'OPTIONS'])

Categories

Resources