JSON XMLHttpRequest POST/PUT to Cherrypy application - getting no data - javascript

I want to create a Singlepage Application following REST principles. I have managed to make both GET and DELETE work, but i also need to PUT or POST data.
After failing for some time, i looked around and found some sample code here https://gist.github.com/EtienneR/2f3ab345df502bd3d13e
which, first of all, taught me that setting a request header may be helpful. With that done, however, and following the exact example, I'm still getting "None" for the field i expect to receive data on.
I may be missing something absolutely basic, and looking around some more i just can't find out what it is.
on the javascript side i've got:
update_px (path_spl, success_ppl, fail_ppl, formdata) {
this.success_p = success_ppl;
this.fail_p = fail_ppl;
var data = {};
data.firstname = "John";
data.lastname = "Snow";
var json = JSON.stringify(data);
var xhr = new XMLHttpRequest();
xhr.open("POST", path_spl, true);
xhr.setRequestHeader('Content-type','application/json; charset=utf-8');
xhr.onload = function () {
var users = JSON.parse(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == "201") {
console.table(users);
} else {
console.error(users);
}
}
xhr.send(json);
}
and on the python side of things:
def POST(self, path_spl="NoPathError", id = None, data_opl=None):
print("POST called with path_spl " + path_spl )
if(id != None) :
print(" and id " + id)
print (data_opl)
#process data
return ' '
The method is exposed; output shows I'm receiving the correct path and ID, but data is just None even after swapping in this sample code i found.
Where am i going wrong?

I have found a way to get it to work.
1) ** was missing on the expected data - that alone didn't help, now i was getting an empty dict instead of None
2) i replaced the content type; the header is now
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
with that, i am receiving:
{'{"firstname":"John","lastname":"Snow"}': ''}
Which actually leads me into another question - how did {"firstname":"John","lastname":Snow"} become a key with an empty value during json-ification? But anyway. That's for another day to find out; i can work with what i'm getting now.

Related

JavaScript - How to send multiple XMLHttp requests or force the XMLHTTP request to wait till I get the desired response?

I am making a GET request to the api using XMLHttpRequests. The api takes in a "uuid" value denoted by the variable "a" here as a parameter, uses that value for processing and is supposed to spit out some information that I am trying to print to the console.
However, the problem I am running into is that, whenever the api successfully receives the uuid value it returns a message where the newresponse.response.status is Initiated. However I want to wait till the newresponse.response.status is Success (this usually takes a short bit like 3-4 seconds more).
The original code is shown below:
function getrequestresults(status, response) {
let parse = JSON.parse(response);
let a = parse.uuid;
let newrequest = new XMLHttpRequest();
newrequest.open('GET', "http://localhost:5000/api/v1/dags/results" + "?" + "uuid" + "=" + a, true);
newrequest.onload = function() {
//console.log(newrequest.status);
console.log(newrequest.response);
};
newrequest.send();
}
One of the attempts I made at fixing this was as follows:
function getrequestresults(status, response) {
let parse = JSON.parse(response);
let a = parse.uuid;
let newrequest = new XMLHttpRequest();
newrequest.open('GET', "http://localhost:5000/api/v1/dags/results" + "?" + "uuid" + "=" + a, true);
newrequest.onload = function() {
while (newrequest.response.status != "Success") {
//the following line was just to see what's going on, idea was to keep looping till, desired status is reached
console.log(newrequest.response);
}
//console.log(newrequest.status);
console.log(newrequest.response);
};
newrequest.send();
}
However, this did not work as it seems that the "onload" function only runs once, whereas I need it to run multiple times until newrequest.response.status is Success.
I am quite new with sending XMLHttpRequests and some help would be appreciated. Thanks.

Randomly occuring Unexpected end of JSON on GET request

I'm developing a simple web project where one of the features (Related to the error) will display a quote, credit and source. This feature works as intended using setInterval every 12seconds to call a function which will make a connection to my XAMPP hosted MYSQL server and return a random row as a JSON object which I can use to display on the page. below is the Quote retrieval script and PHP:
quotes.js
(function() {
ajax = new XMLHttpRequest();
var method = "GET";
var url = "data.php";
var asynchronous = true; // revise asynchronous
var quoteContainer = document.getElementById("quote");
var authorContainer = document.getElementById("author");
function getQuote() {
ajax.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.responseText);
console.log(data)
quoteContainer.innerHTML = "\"" + data.Quote + "\""
authorContainer.innerHTML = data.Author + " - " + "<a href='"+ data.Source +"' target='_blank'>source</a>";
}
}
ajax.open(method,url,asynchronous);
ajax.send();
}
getQuote();
setInterval(getQuote,12000); //set to 100 for testing
}());
Data.php
<?php
// write secondry query for seasonal messages
$conn = mysqli_connect("localhost","root","","quotes_db");
$sql = "SELECT * FROM quote_table ORDER BY RAND() LIMIT 1;";
$result = mysqli_query($conn,$sql);
$data= mysqli_fetch_assoc($result);
echo json_encode($data);
?>
The issue is that on random occasions while this is running the server returns a 'null' packet (with the titled error) I have checked the network data using Chromes developer console and the effected packets are empty and take slightly longer to return. I have checked my database table for special characters and it all seems normal. due to the packet returning null the page is left empty
How can I stop this error appearing, so that I can get a continuous stream of random rows from my table?
If the answer is not an obvious one what bug-testing steps should I take to find a fix?
If more information is needed I can update this post.
Error log
This usually happens when the data returned is undefined or is not in a valid format. That is when JSON.parse() would fail. You can consider putting try-catch block.
try {
var data = JSON.parse(this.responseText);
} catch(e) {
console.log('Unable to parse the string.')
}
Also, consider wrapping the JSON.parse() statement in an if condition, if server sends an empty response.
You can do some kind of error handling to achieve your goal.
ajax.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200) {
try
{
var data = JSON.parse(this.responseText);
}
catch (error)
{
if (error instanceof SyntaxError)
{
// unable to parse the result to json
// maybe retry?
// do some kind of errer handling
}
}
}
Using the try-catch statement you simply catch the error instead of stopping the script from executing so you are able to handle errors yourself.
Best regards.
EDIT:
setInterval(function ()
{
var found = false;
var attemptCount = 0;
var allowedAttempts = 10; // your exit condition, so you wont get stuck in an infinite loop if the server is broken or something
while (!found && attemptCount < allowedAttempts)
{
try
{
getQuote();
}
catch (error)
{
if (error instanceof SyntaxError)
{
attemptCount++;
continue;
}
}
found = true;
}
}, 12e3);
EDIT No.2: (based on your comment on another answer)
If you want to do some server-side validation, you have to modify the PHP-Code:
$data = []; // set a default return value
$result = mysqli_query($conn,$sql);
if (mysqli_num_rows($result) === 1) // we found a result
{
$data= mysqli_fetch_assoc($result);
}
echo json_encode($data);
So, if you combine both, the client- and server-side validation you should be fine for sure:
What did we do?
we implemented a server side validation, so the result that is returned to the client should never throw an error when going through JSON.parse(). To make this work you have to implement a client-side validation on the result of JSON.parse() to make sure that you got a valid result (because it could be an empty array).
if any errors occur on the server (for whatever reason) and the returned result cannot be parsed, we simply retry the entire process for n times.
Best regards.
The issue is caused by your encoding: Jean de La Bruyère is transmitted as Jean de La Bruy�re by MySQL.
PHP json_encode() is not able to deal with the encoding of the French character as shown in this print_r() output of the mysqli_fetch_assoc() result:
Array
(
[QuoteID] => 6
[Quote] => Those who make the worst use of their time are the first to complain of its brevity.
[Author] => Jean de La Bruy�re
[Source] => https://www.goodreads.com/author/show/778012.Jean_de_La_Bruy_re
)
As json_encode() is only accepting UTF-8 encoded strings ("All string data must be UTF-8 encoded.", cf. PHP Documentation), you can tell MySQL to return every result in UTF-8 encoding by simply executing the following query once after opening the connection:
mysqli_query($conn, "SET NAMES 'utf8'");

Cant send Data in AJAX call by using post method

here is my code, its pretty simple and works perfect:
var r = new XMLHttpRequest();
var name='KillerSeba';
r.open("GET","../Serve/servepage.php?name="+name,true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
alert("Success: " + r.responseText);
};
r.send();
This code just sends alert "Success: KillerSeba" when page loads. And my php file which answers request looks kinda of:
<?php
$s=$_REQUEST['name'];
echo $s;
?>
Then i want to use POST method instead of GET one. In order to do this, I change "GET" to "POST", changing url to php file, then add name variable to send() function, so my javascript code look like this:
var r = new XMLHttpRequest();
var name='KillerSeba';
r.open("POST","../Serve/servepage.php",true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
alert("Success: " + r.responseText);
};
r.send(name);
But now script doesnt send any Data to php file, cuz i getting only "Success:" alert. KillerSeba dissipates to somewhere. I tried to use 'name' and "name" instead of name inside of send() function, i tried to replace $_REQUEST by $_POST, but it still doesnt help. So my Queistion is: How to send Data in AJAX Request using POST method? How does this send() function work?
P.S. I prefer to use Vanilla JS Framework only.
As you're sending the name as string without any paramerter name that's why it is not working for you with POST method but when you're sending with GET you're concatenating that name with the url. Now, you've to pass the params the same way you sent with GET method. Just try like this way, I just wrap the name to a variable called params that contains the params = 'name='+name; so you've to send it with your r.send(params). See the examples here both for GET and POST
var r = new XMLHttpRequest();
var name='KillerSeba';
r.open("POST","../Serve/servepage.php",true);
//Send the proper header information along with the request
r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
alert("Success: " + r.responseText);
};
params = 'name='+name;
r.send(params);
You are sending name but without any variable name (it's considered as variable name without any value).
Change your r.send(name); to r.send('name=' + name);.
For more information, take a look at the MDN Web Docs
EDIT: Thanks for your hint, of course you need to set a proper header before sending the request:
r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

How to parse data from this api and display it in my html?

I am brand new to javascript and have spent the past few hours trying to parse json data from an api url into my body in my html document. My only experience with APIs are with C# wrappers so this is new to me.
This is the API url: https://catfact.ninja/fact
I'm not sure where to go from here. I've been able to successfully pull the data I want, but I'm only able to print it to the console and I'm not sure how to pull that data into html. Here is my javascript code:
var HttpClient = function() {
this.get = function(aUrl, aCallback) {
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var anHttpRequest = new XMLHttpRequest();
anHttpRequest.onreadystatechange = function() {
if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200)
aCallback(anHttpRequest.responseText);
}
anHttpRequest.open( "GET", aUrl, true );
anHttpRequest.send( null );
}
}
var client = new HttpClient();
client.get('https://catfact.ninja/fact', function(response) {
var vsplit = response.split("\"")
console.log(vsplit[3]);
$('body').html(document.write(vsplit[3]));
});
Thanks for any help, sorry if I seem dumb
The first issue you have is that the call to document.write in the html function will not produce the results you think. document.write is a synchronous write function that tries to inject a string into the DOM renderer at the point it's called. If you remove that, you should have more luck seeing something in the HTML, but you can also use the following.
The response from https://catfact.ninja/fact is the following.
{"fact":"Cats' eyes shine in the dark because of the tapetum, a reflective layer in the eye, which acts like a mirror.","length":109}
There's no need to split the response when the format is JSON. You can use JSON.parse to create a Javascript Object. For example.
// data will contain data.fact, and data.length
var data = JSON.parse(response);
// Without using jQuery, you can set the html of the body directly
var body = document.getElementsByTagName("body")[0];
body.innerHTML = data.fact;

Using XMLHttpRequest() PUT with GAE Python

I am currently trying to write some Javascript to interact with an API that I deployed on GAE (using Python) using XMXMLHttpRequest(). I've had no issue getting a GET, however the PUT is giving me a lot of trouble.
Interestingly, I have no issue touching the PUT request from a test HTTP site (https://www.hurl.it/), however I receive a status value of 0 every time I try from my own Javascript code. Below are snippets of my GAE and Javascript code.
(NOTE - I must use a "put" for this call as a requirement.)
Any guidance would be appreciated!
GAE (Server):
def put(self):
# Save variables for update
cardkey = self.request.get('key', default_value=None)
ident = self.request.get('ident', default_value=None)
brand = self.request.get('brand', default_value=None)
year = self.request.get('year', default_value=None)
player = self.request.get('player', default_value=None)
# If card key is provided then update card
if cardkey:
# Get card
card_to_update = ndb.Key(db_models.Card, int(cardkey)).get()
if ident:
card_to_update.ident = ident
if brand:
card_to_update.brand = brand
if year:
card_to_update.year = year
if player:
card_to_update.player = player
# Save changes and print update to requester
card_to_update.put()
card_dict_format = card_to_update.to_dict()
self.response.write(json.dumps(card_dict_format))
return
# If card key is not provided send error
else:
self.response.write('key not provided. must provide key for update.')
return
And the Javascript from my webpage:
<script>
window.onload = function()
{
var myRequest = new XMLHttpRequest();
var url = 'http://cs496-assignment3-mastrokn.appspot.com/updatecard';
var param = 'key=5636318331666432';
myRequest.open('put', url);
myRequest.onreadystatechange = function()
{
if ((myRequest.readyState == 4) && (myRequest.status == 200))
{
// var myArr = JSON.parse(myRequst.responseText);
// myFunction(myArr);
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
}
myRequest.send(param);
}
</script>
First, your onreadystatechange() handler should look like this:
myRequest.onreadystatechange = function()
{
if (myRequest.readyState == 4) //Don't do anything until the readyState==4
{
if(myRequest.status == 200) //Check for status==200
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else //All other status codes
{
document.getElementById("viewCards").innerHTML =
'readyState='
+ myRequest.readyState
+ ' status='
+ myRequest.status
+ ' status text='
+ myRequest.statusText;
}
}
}
Then, from the docs:
If you end up with an XMLHttpRequest having status=0 and
statusText=null, it means that the request was not allowed to be
performed. It was UNSENT.
To see what went wrong, check the javascript console in your browser for an error, e.g.:
[Error] XMLHttpRequest cannot load
http://cs496-assignment3-mastrokn.appspot.com/updatecard. Origin
http://localhost:4567 is not allowed by Access-Control-Allow-Origin.
(4.htm, line 0)
When I run the code above and send the XMLHttpRequest to my own local server, the PUT request succeeds with a status code of 200.
Lastly, I have doubts about the server code you posted because I don't know of any framework where you return None from a request handler--rather you return some string or a response object. Yet, using other means to make a PUT request to your url returns a 200 status code. Is that really your server code? What framework are you using?

Categories

Resources