I am fetching data from a URL using an AJAX call. It is giving a json object to me.
When I run the application, the page is working fine in IE with a conformation that
the page is accessing information that is not under its control.
This poses a security risk. Do you want to continue?
But that is not working in other browsers like Firefox, Chrome, Safari, etc.
i don't know what is the problem. Please explain to me why it is occurring and how to solve the issue?
My Code:
<!DOCTYPE html>
<html>
<head>
<title>Search Engine</title>
<script src="JS/jquery-1.4.2.min.js"></script>
<script>
$(document).ready(function () {
$.support.cors = true;
// create a script tag element
var script = document.createElement("script");
// set the attribute, using the URL to pass data via query parameters
script.setAttribute("src", "http://192.168.13.111:7090/?uname=bhagirathip&wt=json&fl=*,score");
script.setAttribute("type", "text/javascript");
// add the script tag to the document head, forcing an HTTP request
document.getElementsByTagName("head")[0].appendChild(script);
});
function Search() {
function callbackJsonHandler(data) {
alert(data); // This is the JSON data
}
}
</script>
</head>
<body>
<form id="form">
<div style="text-align: center">
<input type="search" id="searchInput" autofocus />
<input type="button" id="btnSearch" onclick="Search()" value="Search" />
</div>
</form>
</body>
</html>
You can't make cross-domain AJAX calls across domains. This is a security feature in web browsers to prevent malicious JavaScript code from scraping rendered data in a web page and then shipping it off to some rogue website on some other domain.
By restricting AJAX requests to same domain, browser vendors ensure that JavaScript imported from other sources cannot send data to any server other than the server the HTML page was served from.
In Internet Explorer, it's prompting you, but any smart user who encounters such a message is likely to say no. Presenting your users with such warning messages is not a good design practice and does not inspire confidence in the legitimacy of your application.
The only way that you can send data across domains is to use a browser hack technique called "script tag remoting", which essentially involves using HTML elements that aren't restricted by the same domain policy. For instance script tags can make HTTP GET requests to any server:
// create a script tag element
var script = document.createElement("script");
// set the attribute, using the URL to pass data via query parameters
script.setAttribute("src","http://192.168.9.11/userInput/?key="+userInput);
script.setAttribute("type","text/javascript");
// add the script tag to the document head, forcing an HTTP request
document.getElementsByTagName("head")[0].appendChild(script);
Using this method, you can send data to a remote server. Note that, to get JSON data back, you must wrap it, or pad it, in a JavaScript function and define a callback in the JavaScript code to handle the response:
function callbackJsonHandler(data) {
alert(data); // This is the JSON data
}
And your server-side code must return content text/javascript, calling the handler, and passing your JSON as an argument:
callbackJsonHandler({"key":"value","key1":"value2"});
When the browser downloads the JavaScript to the browser, the JavaScript runs immediately, giving you a hook to use to access the JSON in the response.
Since you're using jQuery, you can also check out jQuery JSONP, or JSON with Padding, which can be used to generate a JavaScript response so that you can handle callbacks from these requests to the remote server. Note that the server must be setup to handle JSONP requests for this to work properly, similar to the above setup.
Another solution to the issue of making cross-domain requests from a browser whose HTML document is served from exampleA.com to a server whose domain is exampleB.com is to use a proxy.
Let's assume that the HTML document you're working with is served from exampleA.com. You own exampleA.com, and you can access the server side and client side code. exampleB.com, on the other hand, is a remote server owned or controlled by someone else. exampleB.com has some data you want to use in exampleA.com.
We know that AJAX won't work, because of the same origin policy, which is in place to protect rogue apps from doing bad things with people's data. However, servers aren't restricted to same domain policy. This means that your app can do the following:
||exampleA.com/test.html|| ---> http req --> ||exampleA.com/getData|| --http req --> ||exampleB.com/getJSON||
Server-side: (As in your server, exampleA.com):
In other words, on your server that you're using to serve the HTML, you write some code that makes an HTTP request from your server to the third-party server:
// JSON URL which should be requested
$json_url = 'http://www.exampleB.com/getJSON';
// Initializing curl
$ch = curl_init( $json_url );
// Configuring curl options
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json')
);
// Setting curl options
curl_setopt_array( $ch, $options );
// Getting results
$result = curl_exec($ch); // Getting JSON result string
See Getting JSON Data with PHP Curl for more details. Each server-side platform has the ability to make HTTP connections to servers.
// now, send the data in the response
HttpResponse::status(200);
HttpResponse::setContentType('application/json');
HttpResponse::setData($result);
HttpResponse::send();
See PHP HTTPResponse. Again, whatever language you're working with should have the ability to return data from a string.
Put the above code in a file called "getJSON.php", assuming you're using PHP. Make sure there is no whitespace between the opening <?php and the beginning of the document; otherwise, you will not be able to set the headers. There is likely a better way to send this response, but since your platform isn't specified, I'll leave that as an exercise for the reader.
Client-side code:
var searchURL = "/getJSON.php"; //From this URL json formatted data is present.
$.ajax({
url: searchURL,
type: 'GET',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
try {
alert(data);
}
catch (err) {
alert(err);
}
}
});
Now, in the above JavaScript code, you make a same-domain AJAX request to your server exampleA.com, and then your server makes a request on your behalf to exampleB.com to get the data, then exampleA.com returns the data in the response to the browser.
Related
While developing a self-contained exist-db app I ran into some issues with passing on the user's identity during an ajax call.
I have created a standard page that allows the user to login in with his or her standard exist-db account. (It's more or less based on this https://github.com/eXist-db/existdb-login ).
At some point, the users need to create their own entries and upload files, and this is done with an ajax script (I'm using Kartik's bootstrap uploader, but it's basically a standard ajax upload function):
$('#input-24').fileinput({
uploadUrl: "../modules/uploader.xql",
uploadAsync: true,
fileActionSettings : {
uploadExtraData() {
return {
'FileName': $(this).data('title'),
}
}
},
});
Now, of course, this will fail, since it will appear like a GUEST user is trying to create entries, which is an action that is allowed only for registered users.
Does exist-db allow a way to send in my login credentials at this point without having to resort to the standard HTTP login (which is problematic, since it means creating a cookie to memorize the password, which more or less renders the whole login suing exist's mechanisms useless), or is there any way to use the controller instead of an external script?
Thanks in advance!
I think you can add the user and password into the URI to trigger the Ajax client to do basic with. e.g. http://username:password#your-server/some/uri/modules/uploader.xql
For simple, basic authentication we do the following since the page itself is being served from xQuery.
step 1: we create in the page xQuery a variable containing the session info. This should be fine for you ... the result of your login would be an HTML page:
let $sessinfo := util:base64-encode(concat(request:get-parameter('user', ()), ":", request:get-parameter('pass', ())))
step 2: during the build of the result page in xQuery, we turn that into a javascript variable through a simple script command placed in <head> tag:
<script>
var sessinfo = "{$sessinfo}";
</script>
step 3: in Javascript loaded with the page (we use jQuery), after the page is ready we setup authentication for all AJAX requests:
jQuery.ajaxSetup({
headers: {
"Authorization": "Basic " + sessinfo
}
});
After that, any AJAX request made would send basic authentication header with user and password to other xQueries executed with jQuery.ajax
To have an eXistdb session work with XHR (Ajax requests) you need make sure that
login:set-user('my.login.domain', (), false())
is called in the controller before you forward it to your request handler. Otherwise all request will seem to originate from the 'guest' user.
If you want to use vanilla/native JavaScript requests e.g. fetch you also need to tell it to add the credentials to the request:
fetch(url, { credentials: 'same-origin', method: 'GET' })
By the way, the persistent login used in exidtb-login likely uses a cookie value to pick up the session variables stored on the server (JSESSIONID), but I need to check that.
I am trying to get the Bitcoin course from a web server.
Then we try it with a JSON from local, it works.
In Firebug, I can see the get request to bitcoincharts.com, but there is no answer.
What's wrong with my code?
$('#LitecoinMenue').append('<p><b>Litecoin: 42</b></p>');
$.getJSON('http://api.bitcoincharts.com/v1/weighted_prices.json',
function(data){
$.each(data.USD, function(index,item){
$('#BitcoinMenue').append('<p><b>Bitcoin:'+ item+'</b></p>');
});
});
The reason your code doesn't work is because of a rule called Same-origin policy. This rule requires that all AJAX requests are made to a file on the same domain name. It is not possible to use $.getJSON, or any other AJAX function to load a file from an external domain.
There are only a few options available, the most common is to create a PHP file to act as a proxy, and store it on the same domain. For example:
proxy.php
<?php
$url = base64_decode($_GET['url']);
return file_get_contents($url);
?>
Your page above
$('#LitecoinMenue').append('<p><b>Litecoin: 42</b></p>');
$.getJSON('proxy.php?url=aHR0cDovL2FwaS5iaXRjb2luY2hhcnRzLmNvbS92MS93ZWlnaHRlZF9wcmljZXMuanNvbg==',
function(data){
$.each(data.USD, function(index,item){
$('#BitcoinMenue').append('<p><b>Bitcoin:'+ item+'</b></p>');
});
});
Important Notes:
This is just an example. In a real life situation you would probably want to use cURL to get your file. You should also ensure that it is secured so that someone cannot use Firebug to send an AJAX request to fetch a big file (like a movie) or your server could crash.
As you can see, the URL is base64 encoded. This is to ensure that it gets processed correctly as sometimes there are issues when passing an unencoded URL as a GET parameter. You can encode and decode base64 strings with these online converters: http://base64encode.org and http://base64decode.org, or you can use the built in PHP functions base64_encode() and base64_decode().
I am trying to create a link on my web page that when accessed will cause an HTTP request with an unordinary method to be sent (for the sake of the example, the method is POSTS).
I know that regular HTML forms support only GET and POST and AJAX should support PUT and delete. Is there a way to issue requests with a method different than these standard HTTP methods?
Thanks in advance.
==============
After the tips I adjusted my page to have the following HTML:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function(){
$("button").click(function(){
$.ajax({url:"http://www.example.php",type:"POSTS",dataType:"html"});
});
});
</script>
</head>
<body>
<button>Send Request</button>
</body>
</html>
Surprisingly, this did not work in Chrome and Firefox but did work in an updated version of IE:
When I tried to issue the request using Firefox and Chrome, the browser issued a request with an OPTIONS method and the following header:
Access-Control-Request-Method: POSTS
Only IE issued the request as per the requirement - using the POSTS HTTP method.
===
Turns out that the aforementioned HTML doesn't work.(The desired request with the custom header is not issued).
As I mentioned above, firefox and chrome issue an initial request with an Access-Control-Request-Method header , while IE doesn't issue a request at all.
I adjusted the browser security settings (enabled "Access data sources across domains),
but still, the browser did not issue the request.
I'm guessing there needs to be some further adjustments in the browser setting, does anyone have an idea how this can be solved?
Quick answer yes if you use javascript.
Methods are defined by the standard along with status codes however they are open to extension. Such as webdav which increases the method vocabulary.
Not all browsers support arbitrary http methods especially older versions of IE (surprise surprise!)
So you could simply have a link / button which calls a javascript function which makes your http request.
Simply using jQuery:
var request = $.ajax({
url: "script.php",
type: "POSTS",
data: { id : menuId },
dataType: "html"
});
request.done(function( msg ) {
$( "#log" ).html( msg );
});
request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});
I am having a rather frustrating problem with the jquery post function that probably stems from not understanding how it works correctly.
I have a function that should post some form information to a php script that I wrote and that script then runs curl requests against an API to get around the cross-domain policy of javascript. It seems to work fine as long as it submits to "http" but when I send it to "https" the form never gets submitted.
I ran wireshark on my computer and it showed no traffic towards the destination ip until I made the url use http. I have basic auth on the server so I am passing the user and password through the url, but tested without that there and got the same results.
Here is the not working code:
$j.post("https://<api user>:<password>#<ip>:444/ProxyScript.php",
$j("#spoke_ticket").serialize(),
function(msg) {
log_status(msg);
fade_status();
$j(':input','#createtheticket')
.not(':button, :submit, :reset, :hidden')
.val('')
.removeAttr('checked')
.removeAttr('selected');
});
Here is the working function:
$j.post("http://<other ip>/ProxyScript.php",
$j("#spoke_ticket").serialize(),
function(msg) {
log_status(msg);
fade_status();
$j(':input','#createtheticket')
.not(':button, :submit, :reset, :hidden')
.val('')
.removeAttr('checked')
.removeAttr('selected');
});
Any ideas as to why the traffic is not being sent?
Let me know if I left out some key information or anything.
Thanks for the help
If you are doing the AJAX post from a http page to a https URL then the Cross-Domain policy kicks in because the protocol is also part of the origin specification, as it is described here. The browser will refuse to make the AJAX call, so that's why you're not seeing any traffic.
A solution is discussed here:
Ajax using https on an http page
So your best bet is the Access-Control-Allow-Origin header which should be supported on most modern browsers now.
So make your server add the following header to the responses:
Access-Control-Allow-Origin: https://www.mysite.com
If for some reason you cannot enforce this, then the only choice left would be JSONP.
Why not use a proxy to get over the cross-domain issue? It sounds more easy. An simple example is when i want to retrieve the danish administration national geo-data for counties,road names and so on (lucky for me, their data is in json or XML optional)
simplified proxy.php
<?
header('Content-type: application/json');
$url=$_GET['url'];
$html=file_get_contents($url);
echo $html;
?>
in ajax, get the lat/longs for a county borderline
var url= "proxy.php?url=https://geo.oiorest.dk/"+type+"/"+nr+"/graense.json";
$.ajax({
url: url,
dataType: 'json',
success: function (data) {
...
});
notice the https - the url could be, real example, https://geo.oiorest.dk/kommuner/0810/graense.json
Here is my situation:
Im creating a widget that site admins can embed in their site and the data are stored in my server. So the script basically has to make an ajax request to a php file in my server to update the database. Right? Right :)
The ajax request works excellent when i run it in my local server but it does not work when the php file is on my ONLINE server.
This is the code im using:
var url = "http://www.mydomain.net/ajax_php.php";
var params = "com=ins&id=1&mail=mymail#site.net";
http.async = true;
http.open("POST", url, true);
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
//do my things here
alert( http.responseText );
}
}
http.send(params);
In firebug it shows: http://www.mydomain.net/ajax_php.php 200 OK X 600ms.
When i check the ajax responnseText I always get a Status:0
Now my question is: "Can i do cross-domain ajax requests by default? Might this be a cross-domain ajax problem? Since it works when the requested file resides in my local server but DOESN'T work when the requested file is in another server, im thinking ajax requests to another remote server might be denied? Can you help me clear on this?
Thanks..
Cross-domain requests are not directly allowed. However, there is a commonly-used technique called JSONP that will allow you to avoid this restriction through the use of script tags. Basically, you create a callback function with a known name:
function receiveData(data) {
// ...
}
And then your server wraps JSON data in a function call, like this:
receiveData({"the": "data"});
And you "call" the cross-domain server by adding a script tag to your page. jQuery elegantly wraps all of this up in its ajax function.
Another technique that I've had to use at times is cross-document communication through iframes. You can have one window talk to another, even cross-domain, in a restricted manner through postMessage. Note that only recent browsers have this functionality, so that option is not viable in all cases without resorting to hackery.
You're going to need to have your response sent back to your client via a JSONP call.
What you'll need to do is to have your request for data wrapped in a script tag. Your server will respond with your data wrapped in a function call. By downloading the script as an external resource, your browser will execute the script (just like adding a reference to an external JS file like jQuery) and pass the data to a known JS method. Your JS method will then take the data and do whatever you need to do with it.
Lots of steps involved. Using a library like jQuery provides a lot of support for this.
Hope this helps.