I try to make an AJAX requestin Chrome using the following code:
var url = "http://" + document.domain + "/status_data.lua?resetsessiontimeout=false";
xmlhttp.open("GET", url, true);
xmlhttp.send(null);
Using WireShark is see that send doesn't send anything... There is no GET emitted.
But if I add an & at the end of the URL:
var url = "http://" + document.domain + "/status_data.lua?resetsessiontimeout=false&";
^
then send will emit the GET request.
Is this expected?
I'm going to guess a couple of common errors people (and I) have made.
Did you create an instance of xmlhttp? In otherwords, do you have a line before your code above that has "var xmlhttp = new XMLHttpRequest();" (case sensitive)
Are you testing this through a file (like C:/test.html) or on a webserver (like Apache or jboss)? If you do the former, you'll get a Cross Point Origin error and doing the latter will fix it.
Are you sure the server code is not looking for additional variables after resetsessiontimeout? Because the '&' is used to delimit additional variables. Although I'm pretty sure it was unneeded to end a variable.
Like if I wanted to send an error string with that url. I can do
resetsessiontimeout=false&errmsg=test
Related
I want to send by XMLHttpRequest a JSON object to a Perl Script (*.cgi)
But I can't decode the JSON object in the cgi file.
I always reveive the error message:
malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before
"(end of string)")
This is my javascript code:
//ajax communication for receiver/transceiver
function doAjaxRequest(query)
{
if(whatReq == "")
{
alert('ERROR: Request-Type undefined');
return;
}
if (window.XMLHttpRequest)
{
arequest = new top.XMLHttpRequest(); // Mozilla, Safari, Opera
}
else if (window.ActiveXObject)
{
try
{
arequest = new ActiveXObject('Msxml2.XMLHTTP'); // IE 5
}
catch (e)
{
try
{
arequest = new ActiveXObject('Microsoft.XMLHTTP'); // IE 6
}
catch (e)
{
alert('ERROR: Request not possible');
return;
}
}
}
if (!arequest)
{
alert("Kann keine XMLHTTP-Instanz erzeugen");
return false;
}
else
{
var url = "****.cgi";
var dp = document.location.pathname;
arequest.open('post', url, true);
arequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
//receiver function
arequest.onreadystatechange = function()
{
switch (arequest.readyState)
{
case 4:
if (arequest.status != 200)
{
alert("Der Request wurde abgeschlossen, ist aber nicht OK\nFehler:"+arequest.status);
}
else
{
var content = arequest.responseText;
analyseResponse(content);
}
break;
default:
//alert("DEFAULT:" + arequest.readyState );
break;
}
}
//transceiver function
query="jsonObj=" + JSON.stringify({name:"John Rambo", time:"2pm"});
alert(query);
arequest.send(query)
}
}
And here the cgi file:
#!/usr/bin/perl
use CGI qw/:standard/;
use CGI::Carp qw(fatalsToBrowser);
use strict;
use warnings;
use JSON;
use Data::Dumper;
my $jsonObj = param('jsonObj');
my $json = JSON->new->utf8;
my $input = $json->decode( $jsonObj );
print Dumper(\$input);
Can you help me? I don't know how to access the JSON object.
Thank you very much.
This message says you've got non-JSON string in $jsonObj. One particulary common case is empty string. Try printing out raw content of $jsonObj and make sure you set up everything correctly for CGI::param to work and also check with browser's built in tools that it actually sends data.
Also I highly suggest you throwing away 10 years old ActiveX shit. You're using JSON.stringify and all the browsers that support it also support native XMLHttpRequest.
I was about to vote to put your question on hold because of insufficient information to reproduce and diagnose the problem, but then I realized that your question does contain enough clues to figure out what's wrong — they're just really well hidden.
Clue #1: Your error message says (emphasis mine):
malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "(end of string)")
This implies that your $jsonObj variable has length 0, i.e. it is empty.
So, what's causing it to be empty? Well, the Perl code looks like perfectly standard CGI stuff, so the problem must be either in your JS code, or in something that your haven't showed us (such as your web server config). Since we can't debug what we can't see, let's focus on your JS code, where we find...
Clue #2: There's something wrong with this line:
arequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
Of course, you can set any content type you want for a POST request, but CGI.pm expects to receive the content in one of the standard formats for HTML form submissions, i.e. either application/x-www-form-urlencoded or multipart/form-data. When it receives something labeled as application/json instead, it doesn't know how to parse it, and so won't. Thus, the param() method in your Perl script will return nothing, since, as far as it's concerned, the client sent no parameters that it could understand.
There should have been a warning about this somewhere in your web server error logs, but you presumably didn't think to check those. (Hint: you really should!)
(You could've also used the warningsToBrowser option of CGI::Carp to get those warnings sent as HTML comments, but I guess you weren't aware of that option, either. Also, to make that work reliably, you'd really need to use CGI::Carp before the CGI module, so that it can catch any early errors.)
Anyway, the fix is simple: just replace application/json in your JS code with application/x-www-form-urlencoded, since that's what what you're actually trying to send to the server. You should also make sure that your JSON data actually is properly URL-encoded before embedding it in the request, by passing the output of JSON.stringify() through encodeURIComponent(), like this:
var data = {name:"John Rambo", time:"2pm"};
var query = "jsonObj=" + encodeURIComponent(JSON.stringify(data));
(I'll also second Oleg V. Volkov's suggestion to get rid of all the obsolete ActiveX stuff in your JS code. In fact, you could do even better by using a modern JS utility library like, say, jQuery, which provides convenient wrapper functions so that you don't even have to mess with XMLHttpRequest directly.)
My XML HTTP request requests a URL that does not exist:
var url = 'http://redHerringObviouslyNonexistentDomainName.com';
var myHttpRequest = new XMLHttpRequest();
myHttpRequest.open('GET', url, true);
myHttpRequest.onreadystatechange = function() {
if (myHttpRequest.readyState == 4 && myHttpRequest.status == 200) {
// Do stuff with myHttpRequest.responseText;
}
}
myHttpRequest.responseType = 'text';
myHttpRequest.send();
I'm OK with the URL not existing ... but I'm not OK with Chrome issuing the following error in the Console:
GET redHerringObviouslyNonexistentDomainName.com/ net::ERR_NAME_NOT_RESOLVED
How do I tell Chrome "I don't care that the URL does not exist - just suppress that error from the Console?"
If someone answers this question by buying that domain name, I will lol so hard ... but then you'll feel bad after I change the URL I use in this question.
as far as this problem, an option would be to send the request to a non-existent ip rather than a non-existent domain because it is throwing that error out of an attempt to find out what ip it points to failing. so by sending it to an ip that you know for a fact will not return anything you may be able to avoid this, although this is purely in theory and you could get an entirely different error thrown at you.
another option is to send the request and have the value returned made into a variable with
errorDomain = yourMethodOfRequestingStatus
this is pure theory and I have not tested any of the suggested methods but I hope it helped you at least a bit.
I'm trying to build a Google query string, make a request to that page, scrape the HTML, and parse it in a Chrome extension, which is JavaScript. So I have the following code:
var url = "https://www.google.com/search?#q=" + artist + "+" + title;
searchGoogleSampleInformation(url);
function searchGoogleSampleInformation(url)
{
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.onreadystatechange = function ()
{
if (xhr.readyState == 4)
{
return parseGoogleInformation(xhr.responseText, url);
}
}
xhr.send();
}
function parseGoogleInformation(search_results, url)
{
var link = $(".srg li.g:eq(0) .r a", search_results).attr('href');
}
The parse method just grabs the url of the first search result (which is not want I'll end up doing, but just to test that the HTTP Request was working). But link is undefined after that line. Then I used alert(url) and verified that my query string was being built correctly; I copied it from the alert window and pasted into another tab, and it pulled up the results as expected. Then I opened a new window with search_results, and it appeared to be Google's regular homepage with no search at all. I thought that problem might be occurring because of the asynchrony of the xhr.open call, but flipping that didn't help either. Am I missing something obvious?
It's because "https://www.google.com/search?#q=" + artist + "+" + title initially has no search results in the content. Google renders the page initially with no results and then dynamically loads the results via JavaScript. Since you are just fetching the HTML of the page and processing it the JavaScript in the HTML never gets executed.
You are making a cross domain Ajax call, which is not allowed by default. You cannot make a cross domain call unless the server supports it and you pass the appropriate headers.
However, as you mentioned you are building a Chrome extension, it is possible by adding a few fields in the manifest file: https://developer.chrome.com/extensions/xhr#requesting-permission
I'm trying to write a plugin. I can not use any libraries or frameworks.
At any website (domain) I would like to start a script from my own domain.
For example:
In the code of the website under domain A I put a code starting the script from domain B
<script src="http://domain-b.com/myscript.js" type="text/javascript"></script>
The code of JavaScript (myscript.js)
type = 'GET';
url = 'http://domain-b.com/echojson.php';
data = ‘var1=1&var2=2’;
_http = new XMLHttpRequest();
_http.open(type, url + '?callback=jsonp123' + '&' + data, true);
_http.onreadystatechange = function() {
alert(‘Get data: ’ + _http.responseText);
}
_http.send(null);
Script from http://domain-b.com/echojson.php always gives the answer:
jsonp123({answer:”answer string”});
But in a JavaScript console I see an error (200) and AJAX doesn’t get anything.
Script loaders like LAB, yep/nope or Frame.js were designed to get around the same-origin policy. They load a script file, so the requested file would have to look like:
response = {answer:”answer string”};
If you use your code like you have posted it here, it does not work, because you are using apostrophs for the data variable!
Edit: Maybe I made the question more complex than it should. My questions is this: How do you make API calls to a server from JS.
I have to create a very simple client that makes GET and POST calls to our server and parses the returned XML. I am writing this in JavaScript, problem is I don't know how to program in JS (started to look into this just this morning)!
As n initial test, I am trying to ping to the Twitter API, here's the function that gets called when user enters the URL http://api.twitter.com/1/users/lookup.xml and hits the submit button:
function doRequest() {
var req_url, req_type, body;
req_url = document.getElementById('server_url').value;
req_type = document.getElementById('request_type').value;
alert("Connecting to url: " + req_url + " with HTTP method: " + req_type);
req = new XMLHttpRequest();
req.open(req_type, req_url, false, "username", "passwd");// synchronous conn
req.onreadystatechange=function() {
if (req.readyState == 4) {
alert(req.status);
}
}
req.send(null);
}
When I run this on FF, I get a
Access to restricted URI denied" code: "1012
error on Firebug. Stuff I googled suggested that this was a FF-specific problem so I switched to Chrome. Over there, the second alert comes up, but displays 0 as HTTP status code, which I found weird.
Can anyone spot what the problem is? People say this stuff is easier to use with JQuery but learning that on top of JS syntax is a bit too much now.
For security reasons, you cannot use AJAX to request a file from a different domain.
Since your Javascript isn't running on http://api.twitter.com, it cannot request files from http://api.twitter.com.
Instead, you can write server-side code on your domain to send you the file.