Receiving AJAX Data on Cherrypy: 400 Bad Request from Javascript Post Request - javascript

I'm fairly new to web development. I am currently trying to make a post request from my javascript website to my separately hosted python code (using cherrypy), and have received a "400 Bad Request" in the console of my web browser.
I think the issue may be with the cherrypy method I took from the link shown in the code, or with "data" in the javascript code. Cherrypy works fine for everything else in my Python code (none of the other methods involve receiving data from javascript, but rather python). I finally created a stackoverflow account after being stuck on this for a while. The exact error given in the browser console is: "Post [url] 400 (Bad Request)"
Any help would be greatly appreciated.
// From the Website (Post Request):
$.ajax({
url:'relevanturl',
type:"POST",
// id, title, start_time, and end_time are strings, and userlist is an array of strings
data:{id:id, title:title, start_time:start_time, end_time:end_time, userlist:userlist},
success:function() {
},
error:function(jqXHR,textStatus,errorThrown
{alert('Exception:'+errorThrown);}
});
# The specific cherrypy method not working (I made it with help from
# this link that shows how to handle AJAX requests:
# https://stackoverflow.com/questions/3743769/how-to-receive-json-in-a-post-request-in-cherrypy
#cherrypy.expose
def add_meeting(self, data=None):
cl = cherrypy.request.headers['Content-Length']
rawbody = cherrypy.request.body.read(int(cl))
body = simplejson.loads(rawbody)
# For now, I'm just trying to receive the data from the website.
print(body)

The information from the link in the comments solved the problem.
How to receive JSON in a POST request in CherryPy?
The solution was to convert the data into JSON, and follow the necessary $.ajax syntax for JSON. To receive the data with CherryPy, #cherrypy.tools.json_in() must be called along with the usual "expose," and all the other relevant Python code from the link.
Thank you!

Related

Send JSON data to Flask server using JQuery .load()

I am trying to use JQuery's .load() function to send data to my Flask server and, using that, render a <div> that is loaded into the calling element. My call looks something like this:
$("#element").load(
"/get_data",
{"info": info} // this is the problem
)
However, when I try to access this data in my Flask backend, the data is of form byte-string. (Accessing with request.get_data() yields a byte-string and request.get_json() yields None).
This did not surprise me, as the same behavior occurs when I use .ajax() requests. With Ajax, I simply use data: JSON.stringify({"info":info}) and that sends a string easily read by json.loads to the Flask backend just fine. What befuddles me is when I attempt the same data packaging with .load(), the request to the server is a GET instead of a POST.
Per .load()'s documentation, "The POST method is used if data is provided as an object; otherwise, GET is assumed." I don't understand why the data being a JSON string alters the behavior of .load() this way.
I'm keen to understand this behavior, but my question is how can I send data using JQuery's .load() to a Flask backend as a POST request in form JSON, or at least readable as a json (e.g. JSON string)?
Your code should work. You have data as {"info": info}, which is an object that .load should send as a POST. Make sure you are getting a JSON mimetype object from the server. Also, make sure your Flask view accepts the POST method:
from flask import Flask, request, Response
import json
#app.route('/get_data', methods = ['GET', 'POST'])
def get_data():
payload_dict = json.loads(request.data.decode('utf-8'))
# or try payload_dict = request.json
print(payload_dict["info"])
return Response(json.dumps({"info_response": "hello"}), mimetype='application/json')
And make sure you have info defined in {"info": info}
Thought about using getJSON: https://api.jquery.com/jQuery.getJSON/ ?

Execute Javascript function from HTML Request

I'm new to JS and am trying to execute a function on a site to pull all the data in table in JSON format.
I am using Parse Cloud Code to send my http requests, and the requests themselves are working, but I can't seem to get just the data itself.
It seems I am only able to get it in HTML and even then the objects do not display the same way that they do in the webpage's elements.
Any help/advice would be greatly appreciated!
Thank you in advance.
This is the link:
http://www.capetown.gov.za/Media-and-news#k=thinkwater
Here is the code:
Parse.Cloud.define('hello', function(req, res) {
res.success('Hi');
});
Parse.Cloud.define('htmlTest', function(req, res) {
Parse.Cloud.httpRequest({
method: 'POST',
url: 'http://www.capetown.gov.za/Media-and-news#k=thinkwater',
params: {
action: '/Media-and-news',
id: 'aspnetForm',
onsubmit: 'javascript:return WebForm_OnSubmit();'
},
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
}).then(function(httpResponse) {
// success
res.success(httpResponse.text);
}, function(httpResponse) {
// error
res.error('Request failed with response code ' + httpResponse.status);
});
});
You can't execute client-side JavaScript function with an HTTP request.
Here's what happens when you load that page:
Server (the site you're trying to fetch) receives an HTTP request (from you)
Server generates initial HTML and responds to whoever made the above request, be it a browser, or your NodeJS Code. This "initial" HTML is what you get with a simple HTTP request. (which in your case doesn't contain the results you need)
If the HTML was served inside a browser, additional client-side JavaScript code is executed (i.e. the "javascript function" which you're trying to want to execute). This can only happen in a browser (or browser-like) environment. This JavaScript code (or function) modifies HTML (when loaded in a browser-environment, using DOM) and thus the final HTML is rendered. You can't get to these results with a simple HTTP request*, as that will only get you till #2.
*You can find out which URL the client javascript uses to fetch those results itself. Network tab in console tools might help with this. When you click on the button that triggers it to fetch the results keep an eye on which requests are made.
.
In your case it seems to be fetching JSON with a POST request from http://www.capetown.gov.za/_vti_bin/client.svc/ProcessQuery although it doesn't seem straightforward, it makes a series of requests each depending on the previous one, at least that's what it seems on the first glance. Feel free to explore this route yourself.
So in order to get the final HTML you will either
Need the direct URL that serves those results. This is usually the quickest but requires understanding the site's API and how it fetches results if it does so via AJAX (fetching via client-side JavaScript)
Use a fetcher with a browser or browser-like environment. E.g. PhantomJS (deprecated), Puppeteer, selenium, zombie

sending local mp3 file to api server using jquery

I wish to use echoprint - http://echoprint.me/start - which allows me to send an mp3 file locally from my computer in a post request, and returns a json object including the song's details from their server.
I am attempting to make this post request using jquery in order to allow me retrieve the json object containing the song details, which will then allow me view this in my browser's console.
The echoprint website - http://developer.echonest.com/docs/v4/track.html - explains how to make this post request using curl. The following code works in the command line. This returns a json object, however this gets returned in the terminal.
curl -F "api_key=#############" -F "filetype=mp3" -F "track=#tambourineMan.mp3" "http://developer.echonest.com/api/v4/track/upload"
I have read the curl docs http://curl.haxx.se/docs/httpscripting.html#POST to try and understand where the correlation exists between the curl and jquery, but unfortunately I am having difficulties relating the two and understanding what -F means.
My aim is to make this post request using jquery so I can make the same request as outlined using curl above, and retrieve the json data in the browser's console.
From a previous question I asked on here I have tried to adopt the logic from that answer and used the following code, however this returns an error that the file cannot be encoded. I have tried it with and without the content type specified, but both methods fail.
$.post("http://developer.echonest.com/api/v4/track/upload", {
"api_key":"##################",
"track":"#tambourineMan.mp3",
"filetype":"mp3",
"contentType:" "application/octet-stream"
},
function( data ) {
console.log(data)
},
"JSON" );
There are instructions here http://developer.echonest.com/docs/v4/track.html but they only explain how to do this using curl. If anyone could shed any light on this it would be greatly appreciated. Pardon my ignorance in advance.
cURL uses the # prefix to mean "the contents of the named file", in your AJAX request you are sending #tambourineMan.mp3 as a literal string.
One easy to way to accomplish your task is to put a file input in your document and tell jQuery to use the data from that file:
var file = document.getElementById('myFileInput').files[0];
$.post("http://developer.echonest.com/api/v4/track/upload", {
"api_key":"##################",
"track":file,
"filetype":"mp3",
"contentType:" "application/octet-stream"
});
Take a look at the FileReader API and at this article about sending and receiving binary data in a XMLHttpRequest

How to manually submit a post request to a server?

I am looking for a way to manually submit a Post request to a server, without using the website's UI. I can see the request headers and the post parameters in Firebug when I perform the action manually (clicking the UI's "submit" button). I am hoping there is a way to reverse engineer some Javascript using these headers and parameters so that we can automate this process.
Reason: My company recently purchased some process automation software that enables us to write automation bots that access out business partner's portal site and automatically adjust our digital marketing bids. For one of our partner sites, front-end manipulation doesn't appear to work, because the Post request is submitted via AJAX.
The software does allow us to execute custom javascript within the environment, so I am trying to construct some Javascript using the headers and request parameters.
Is there a standard template into which I can plug these parameters to execute Javascript that will send the Post request to the server?
Thank you
UPDATE:
Thank you all for your help! I've made some progress but am still having difficulty implementing the solution within the software.
The following request works when I run the code in Firebug in Firefox:
$.ajax({
type: "POST",
url: "http://acp.example.com/campaigns/122828",
data: "data-string"
});
However, the software we're using might be a little out of date and I'm not sure it recognizes the AJAX syntax.
Is there a way to effectively write the same statement above, but in Javascript rather than AJAX? Then I think it would work.
You can use AJAX to post data to a server without any direct UI interaction. I will break down a simple jQuery example below:
$.ajax({
type: "POST",
url: url,
data: data,
success: success,
});
$.ajax Is a method offered by the jQuery framework to make AJAX requests simple and cross browser compatible. As you can see I have passed in a JSON object containing various values:
type - This is the first key I have specified, in this instance you'll want this to be of the value POST as this determines the HTTP Request Method.
url - This specifies the server end point, for example: post/data/here.php would post the data to that url so that it can be picked up and handled correctly.
data - This key expects a JSON object, string or array of data to send in the POST request.
success - This key expects a function, it is called on the server's response to the request, with any relevant data passed through.
More documentation is available at: http://api.jquery.com/jquery.ajax/
If all you want to do is POST data, no JavaScript needed.
You should be able to use a browser extension for this. I have one called REST Console that is similar to what you describe. I believe REST Console is for Chrome only, but a quick Google search yielded a similar looking extension for FireFox called RESTClient.

Can't log into Tiny Tiny RSS API using Prototype.js

I am attempting to build a reader for Tiny Tiny RSS and am stuck almost at square one. I'm setting the app up to use ajax via prototype.js (1.6.1) and am attempting a simple login to the app to retrieve a key.
Here's what I have so far:
new Ajax.Request(Api.BASE_URL, {
method: "get",
parameters: {"op": "login", "user": "user", "password": "password"},
onSuccess: authSuccess,
onFailure: failure
})
Where Api.BASE_URL is defined as "http://tt-rss.example.com/api/"
When I try to log in I get the error response "NOT_LOGGED_IN", which appears to indicate that the api either does not recognize the op call that I am using, or the parameters are wrong, or something.
What is particularly odd is that this should be equivalent to the CURL command:
curl -d '{"op":"login","user":"user","password":"password"}' http://tt-rss.example.com/api/
Which works properly. I get the feeling that I am missing something incredibly simple, but am not sure what it is. Any help would be much appreciated.
In addition to the get vs post error, it turns out that the problem was that I was trying to pass a complex json object using the wrong ajax option.
I tested with a simpler function call (isloggedin), so my json object was defined as:
parameters: {"op": "isloggedin"},
When I used the "parameters" ajax option, the request was sending raw data in the form of:
op=isloggedin&_=
Which was getting rejected.
On the other hand, the raw data from cURL looked like:
{"op":"isloggedin"}
Which was working.
This post put me on the right track. I needed to use "postBody" instead of "parameters" to send the data properly. My final command wound up looking like this:
postBody: '{"op": "isloggedin"}',
And it worked. Also, apparently in this case type of quotes does matter. If I used single quotes on the outside, it worked. If I used double quotes on the outside if failed.
Your curl command sends data in a POST request, whereas the Ajax call uses the GET method. According to the tt-rss API documentation, older versions supported both GET and POST, but now data must be encoded using JSON in HTTP POST data.

Categories

Resources