I'm trying to load a cross-domain HTML page using AJAX but unless the dataType is "jsonp" I can't get a response. However using jsonp the browser is expecting a script mime type but is receiving "text/html".
My code for the request is:
$.ajax({
type: "GET",
url: "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P#ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute",
dataType: "jsonp",
}).success( function( data ) {
$( 'div.ajax-field' ).html( data );
});
Is there any way of avoiding using jsonp for the request? I've already tried using the crossDomain parameter but it didn't work.
If not is there any way of receiving the html content in jsonp? Currently the console is saying "unexpected <" in the jsonp reply.
jQuery Ajax Notes
Due to browser security restrictions, most Ajax requests are subject to the same origin policy; the request can not successfully retrieve data from a different domain, subdomain, port, or protocol.
Script and JSONP requests are not subject to the same origin policy restrictions.
There are some ways to overcome the cross-domain barrier:
CORS Proxy Alternatives
Ways to circumvent the same-origin policy
Breaking The Cross Domain Barrier
There are some plugins that help with cross-domain requests:
Cross Domain AJAX Request with YQL and jQuery
Cross-domain requests with jQuery.ajax
Heads up!
The best way to overcome this problem, is by creating your own proxy in the back-end, so that your proxy will point to the services in other domains, because in the back-end not exists the same origin policy restriction. But if you can't do that in back-end, then pay attention to the following tips.
**Warning!**
Using third-party proxies is not a secure practice, because they can keep track of your data, so it can be used with public information, but never with private data.
The code examples shown below use jQuery.get() and jQuery.getJSON(), both are shorthand methods of jQuery.ajax()
CORS Anywhere
2021 Update
Public demo server (cors-anywhere.herokuapp.com) will be very limited by January 2021, 31st
The demo server of CORS Anywhere (cors-anywhere.herokuapp.com) is meant to be a demo of this project. But abuse has become so common that the platform where the demo is hosted (Heroku) has asked me to shut down the server, despite efforts to counter the abuse. Downtime becomes increasingly frequent due to abuse and its popularity.
To counter this, I will make the following changes:
The rate limit will decrease from 200 per hour to 50 per hour.
By January 31st, 2021, cors-anywhere.herokuapp.com will stop serving as an open proxy.
From February 1st. 2021, cors-anywhere.herokuapp.com will only serve requests after the visitor has completed a challenge: The user (developer) must visit a page at cors-anywhere.herokuapp.com to temporarily unlock the demo for their browser. This allows developers to try out the functionality, to help with deciding on self-hosting or looking for alternatives.
CORS Anywhere is a node.js proxy which adds CORS headers to the proxied request.
To use the API, just prefix the URL with the API URL. (Supports https: see github repository)
If you want to automatically enable cross-domain requests when needed, use the following snippet:
$.ajaxPrefilter( function (options) {
if (options.crossDomain && jQuery.support.cors) {
var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
//options.url = "http://cors.corsproxy.io/url=" + options.url;
}
});
$.get(
'http://en.wikipedia.org/wiki/Cross-origin_resource_sharing',
function (response) {
console.log("> ", response);
$("#viewer").html(response);
});
Whatever Origin
Whatever Origin is a cross domain jsonp access. This is an open source alternative to anyorigin.com.
To fetch the data from google.com, you can use this snippet:
// It is good specify the charset you expect.
// You can use the charset you want instead of utf-8.
// See details for scriptCharset and contentType options:
// http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
$.ajaxSetup({
scriptCharset: "utf-8", //or "ISO-8859-1"
contentType: "application/json; charset=utf-8"
});
$.getJSON('http://whateverorigin.org/get?url=' +
encodeURIComponent('http://google.com') + '&callback=?',
function (data) {
console.log("> ", data);
//If the expected response is text/plain
$("#viewer").html(data.contents);
//If the expected response is JSON
//var response = $.parseJSON(data.contents);
});
CORS Proxy
CORS Proxy is a simple node.js proxy to enable CORS request for any website.
It allows javascript code on your site to access resources on other domains that would normally be blocked due to the same-origin policy.
CORS-Proxy gr2m (archived)
CORS-Proxy rmadhuram
How does it work?
CORS Proxy takes advantage of Cross-Origin Resource Sharing, which is a feature that was added along with HTML 5. Servers can specify that they want browsers to allow other websites to request resources they host. CORS Proxy is simply an HTTP Proxy that adds a header to responses saying "anyone can request this".
This is another way to achieve the goal (see www.corsproxy.com). All you have to do is strip http:// and www. from the URL being proxied, and prepend the URL with www.corsproxy.com/
$.get(
'http://www.corsproxy.com/' +
'en.wikipedia.org/wiki/Cross-origin_resource_sharing',
function (response) {
console.log("> ", response);
$("#viewer").html(response);
});
The http://www.corsproxy.com/ domain now appears to be an unsafe/suspicious site. NOT RECOMMENDED TO USE.
CORS proxy browser
Recently I found this one, it involves various security oriented Cross Origin Remote Sharing utilities. But it is a black-box with Flash as backend.
You can see it in action here: CORS proxy browser
Get the source code on GitHub: koto/cors-proxy-browser
You can use Ajax-cross-origin a jQuery plugin.
With this plugin you use jQuery.ajax() cross domain. It uses Google services to achieve this:
The AJAX Cross Origin plugin use Google Apps Script as a proxy jSON
getter where jSONP is not implemented. When you set the crossOrigin
option to true, the plugin replace the original url with the Google
Apps Script address and send it as encoded url parameter. The Google
Apps Script use Google Servers resources to get the remote data, and
return it back to the client as JSONP.
It is very simple to use:
$.ajax({
crossOrigin: true,
url: url,
success: function(data) {
console.log(data);
}
});
You can read more here:
http://www.ajax-cross-origin.com/
If the external site doesn't support JSONP or CORS, your only option is to use a proxy.
Build a script on your server that requests that content, then use jQuery ajax to hit the script on your server.
Just put this in the header of your PHP Page and it ill work without API:
header('Access-Control-Allow-Origin: *'); //allow everybody
or
header('Access-Control-Allow-Origin: http://codesheet.org'); //allow just one domain
or
$http_origin = $_SERVER['HTTP_ORIGIN']; //allow multiple domains
$allowed_domains = array(
'http://codesheet.org',
'http://stackoverflow.com'
);
if (in_array($http_origin, $allowed_domains))
{
header("Access-Control-Allow-Origin: $http_origin");
}
I'm posting this in case someone faces the same problem I am facing right now. I've got a Zebra thermal printer, equipped with the ZebraNet print server, which offers a HTML-based user interface for editing multiple settings, seeing the printer's current status, etc. I need to get the status of the printer, which is displayed in one of those html pages, offered by the ZebraNet server and, for example, alert() a message to the user in the browser. This means that I have to get that html page in Javascript first. Although the printer is within the LAN of the user's PC, that Same Origin Policy is still staying firmly in my way. I tried JSONP, but the server returns html and I haven't found a way to modify its functionality (if I could, I would have already set the magic header Access-control-allow-origin: *). So I decided to write a small console app in C#. It has to be run as Admin to work properly, otherwise it trolls :D an exception. Here is some code:
// Create a listener.
HttpListener listener = new HttpListener();
// Add the prefixes.
//foreach (string s in prefixes)
//{
// listener.Prefixes.Add(s);
//}
listener.Prefixes.Add("http://*:1234/"); // accept connections from everywhere,
//because the printer is accessible only within the LAN (no portforwarding)
listener.Start();
Console.WriteLine("Listening...");
// Note: The GetContext method blocks while waiting for a request.
HttpListenerContext context;
string urlForRequest = "";
HttpWebRequest requestForPage = null;
HttpWebResponse responseForPage = null;
string responseForPageAsString = "";
while (true)
{
context = listener.GetContext();
HttpListenerRequest request = context.Request;
urlForRequest = request.RawUrl.Substring(1, request.RawUrl.Length - 1); // remove the slash, which separates the portNumber from the arg sent
Console.WriteLine(urlForRequest);
//Request for the html page:
requestForPage = (HttpWebRequest)WebRequest.Create(urlForRequest);
responseForPage = (HttpWebResponse)requestForPage.GetResponse();
responseForPageAsString = new StreamReader(responseForPage.GetResponseStream()).ReadToEnd();
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Send back the response.
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseForPageAsString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
response.AddHeader("Access-Control-Allow-Origin", "*"); // the magic header in action ;-D
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
//listener.Stop();
All the user needs to do is run that console app as Admin. I know it is way too ... frustrating and complicated, but it is sort of a workaround to the Domain Policy problem in case you cannot modify the server in any way.
edit: from js I make a simple ajax call:
$.ajax({
type: 'POST',
url: 'http://LAN_IP:1234/http://google.com',
success: function (data) {
console.log("Success: " + data);
},
error: function (e) {
alert("Error: " + e);
console.log("Error: " + e);
}
});
The html of the requested page is returned and stored in the data variable.
To get the data form external site by passing using a local proxy as suggested by jherax you can create a php page that fetches the content for you from respective external url and than send a get request to that php page.
var req = new XMLHttpRequest();
req.open('GET', 'http://localhost/get_url_content.php',false);
if(req.status == 200) {
alert(req.responseText);
}
as a php proxy you can use https://github.com/cowboy/php-simple-proxy
Your URL doesn't work these days, but your code can be updated with this working solution:
var url = "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P#ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute";
url = 'https://google.com'; // TEST URL
$.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURI(url), function(data) {
$('div.ajax-field').html(data);
});
<div class="ajax-field"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You need CORS proxy which proxies your request from your browser to requested service with appropriate CORS headers. List of such services are in code snippet below. You can also run provided code snippet to see ping to such services from your location.
$('li').each(function() {
var self = this;
ping($(this).text()).then(function(delta) {
console.log($(self).text(), delta, ' ms');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/jdfreder/pingjs/c2190a3649759f2bd8569a72ae2b597b2546c871/ping.js"></script>
<ul>
<li>https://crossorigin.me/</li>
<li>https://cors-anywhere.herokuapp.com/</li>
<li>http://cors.io/</li>
<li>https://cors.5apps.com/?uri=</li>
<li>http://whateverorigin.org/get?url=</li>
<li>https://anyorigin.com/get?url=</li>
<li>http://corsproxy.nodester.com/?src=</li>
<li>https://jsonp.afeld.me/?url=</li>
<li>http://benalman.com/code/projects/php-simple-proxy/ba-simple-proxy.php?url=</li>
</ul>
Figured it out.
Used this instead.
$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');
I am trying to play an audio using Google Text-To-Speech. Therefore I need to post a request to their endpoint with the Referer and the User-Agent properly set. This call should return an MP3 that I can play.
However, I get Refused to set unsafe header errors. This is my code. How can I do this?
$.ajax({
url: 'http://translate.google.com/translate_tts?ie=UTF-8&q=Hello&tl=en&client=t',
beforeSend: function(xhr) {
xhr.setRequestHeader("Referer", "http://translate.google.com/");
xhr.setRequestHeader("User-Agent", "stagefright/1.2 (Linux;Android 5.0)");
}, success: function(data){
el.mp3 = new Audio(data);
el.mp3.play();
}
});
You can't. It is impossible.
The specification requires that the browser abort the setRequestHeader method if you try to set the Referer header (it used to be that User-Agent was also forbidden but that has changed)..
If you need to set Referer manually then you'll need to make the request from your server and not your visitor's browser.
(That said, if you need to be deceptive about the user agent or referer then you are probably trying to use the service in a fashion that the owner of it does not want, so you should respect that and stop trying).
Note that while jQuery wraps XHR, the same rules apply to fetch.
Empty Origin and Referer headers with GET XMLHttpRequest from <iframe>
Well actually, it is possible; at least for ordinary web pages.
The trick consists in injecting an XMLHttpRequest
function into an empty <iframe>.
The origin of an empty <iframe> happens to be about://blank, which results in empty Origin and Referer HTTP headers.
HTML:
<iframe id="iframe"></iframe>
JavaScript:
const iframe = document.getElementById('iframe');
const iframeWin = iframe.contentWindow || iframe;
const iframeDoc = iframe.contentDocument || iframeWin.document;
let script = iframeDoc.createElement('SCRIPT');
script.append(`function sendWithoutOrigin(url) {
var request = new XMLHttpRequest();
request.open('GET', url);
request.onreadystatechange = function() {
if(request.readyState === XMLHttpRequest.DONE) {
if(request.status === 200) {
console.log('GET succeeded.');
}
else {
console.warn('GET failed.');
}
}
}
request.send();
}`);
iframeDoc.documentElement.appendChild(script);
JavaScript evocation:
var url = 'https://api.serivce.net/';
url += '?api_key=' + api_write_key;
url += '&field1=' + value;
iframeWin.sendWithoutOrigin(url);
Having the possibility of sending empty Origin and Referer HTTP headers is important to safeguard privacy when using third-party API services. There are instances where the originating domain name may reveal sensitive personal information; like being suggestive of a certain medical condition for example. Think in terms of https://hypochondriasis-support.org :-D
The code was tested by inspecting the requests in a .har file, saved from the Network tab in the F12 Developer View in Vivaldi.
No attempt in setting the User-Agent header was made. Please, comment if this also works.
There are some header, which browser doesn't allow programmer to set its value in any of the javascript framework (like jQuery, Angular, etc.) or XMLHttpRequest ; while making AJAX request. These are called the forbidden headers: Forbidden Header
I have two different servers and each have their own domain. I'm running an ajax script from one server to the other server. I am receiving the "No 'Access-Control-Allow-Origin'" error, BUT my server side script is still processing the request.
Is there a reason my server side script is processing the ajax request even though it is a CORS violation?
Update: Here is my code
var init,
yourname,
youremail,
friendname,
friendemail,
message,
url,
data,
request;
init = function() {
yourname = $('input[name=yourName]').val();
youremail = $('input[name=yourEmail]').val();
friendname = $('input[name=friendName]').val();
friendemail = $('input[name=friendEmail]').val();
message = $('textarea[name=comments]').val();
url = window.location.href;
data ='yourName=' + yourname + '&yourEmail=' + youremail + '&friendName=' + friendname + '&friendEmail=' + friendemail + '&comments=' + message + '&url=' + url;
request = $.ajax({
type: 'POST',
url: features.captureForm.processing,
data: data,
cache: false
});
request.done(function() {
$('#form').css({'height':'0','overflow':'hidden'});
$('#formHeader').find('h2').html('Thank you!');
setTimeout(function(){
HideShowForm.init();
$('#form').css({'height':'auto'});
$('#formHeader').find('h2').html('Send to a friend!');
},3000);
});
request.fail(function() {
console.log('Something went wrong');
});
};
The request is sent and your server will process it as usual. Only its response will not be available for the client script. That is the point where CORS allows or denies anything, not when sending the request.
This is a simple misunderstanding of CORS on your part.
If the request is a "simple" cross-origin request (GET, POST, HEAD), it is no different than any cross-origin browser-based request that your server could have received before the CORS spec was drafted and implemented. The CORS spec wasn't designed to protect your server from such requests: it never was protected by default. If you want to discard such requests, you can look at the origin in your server code and simply not perform the requested operation if you prefer.
Non-simple cross-origin requests, such as PUT or DELETE requests, will invoke a "preflight" (OPTIONS) request by the browser, essentially asking your server "Is it ok to send this request?" Only if your server properly acknowledges will the underlying request will be sent. These types of non-simple cross-origin browser-based requests were not possible before the CORS spec, hence the additional layer of protection for older servers or those that don't want to opt-in to these new cross-origin requests.
Note that there are other factors that make a cross-origin request simple or not.
in a web page, is there a way to detect by javascript if a web browser is using a PAC file http://xxx.xx.xx.xxx/toto.pac ?
Notes : the same page can be viewd behind many PACs, i don't want to use a server end language, i can edit the toto PAC file if necessary. Regards
You could make an ajax request to a known external server (google.com) and then get the headers out of that request to see if the proxy headers are in the request...
var proxyHeader = 'via';
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send();
var header = req.getResponseHeader(proxyHeader);
if (header) {
// we are on a proxy
}
Change proxyHeader to what ever your proxy adds to the response.
EDIT: You will have to add a conditional for supporting the IE implementation of XMLHttpRequest
EDIT:
I am on a proxy at work and I have just tested this code in jsfiddle and it works. Could be made prettier so that is supports IE and does an async get but the general functionality is there... http://jsfiddle.net/unvHW/
It turns out that detecting 'via' is much better...
Note that this solution will not work on every proxy and would probably only work if you are BEHIND the proxy :
Some proxies append a field in the response headers of an HTTP request which is called : X-Forwarded-For
Maybe you can achieve what you are trying to do with an AJAX request to google.com for example and check if the field is there.
Something like this :
$.ajax({
type: 'POST',
url:'http://www.google.com',
data: formData,
success: function(data, textStatus, request){
if(request.getResponseHeader('X-Forwarded-For')) !== undefined)
alert("Proxy detected !");
}
});
Edit: As Michael said, the X-Forwarded-For is only appended to requests. You'd better check for the response header your proxy puts in the response header.
No.
Browsers do not expose that sort of configuration data to websites.
I had read earlier that cross domain requests are not possible through AJAX (since XHR is bound to same origin policy)... Hence we use JSONP, which uses dynamic script injection (since script tag is not bound by same origin policy).
However, I was going through the jQuery AJAX documentation and saw one setting saying "crossDomain".
So, is Cross domain requests now supported through jQuery/AJAX? Is it the same as what we get through JSONP?
I made a project that use cross domain requests. You have few examples.
It is here, on Github.
Use this function in your client-side code (javascript):
function getHTML(url, callback){
url = url.trim();
$.ajax({
url: url,
type: 'GET',
success: function(res) {
var headline = res.responseText;
if(headline === ""){
callback("There was a problem with the page. Be sure that your url is correct.");
return;
}
callback(null, headline);
}
});
}