Loading cross-domain endpoint with AJAX
Asked Answered
W

9

138

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.

Weston answered 21/2, 2013 at 15:4 Comment(2)
I have resolved the problem by creating a proxy.php as explained here scode7.blogspot.com/2019/11/…Liability
Thanks CodeDezk, I created my own PHP proxy for cross-domain AJAX requests following your link. It was super easy.Alpestrine
M
242

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:

There are some plugins that help with cross-domain requests:

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:

  1. The rate limit will decrease from 200 per hour to 50 per hour.
  2. By January 31st, 2021, cors-anywhere.herokuapp.com will stop serving as an open proxy.
  3. 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.

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

Mitchmitchael answered 25/6, 2013 at 14:18 Comment(14)
You can also deploy your own version of WhateverOrigin.org (or port the code for your own use) from here: github.com/ripper234/Whatever-OriginCanaanite
I have tried this code it works properly to load HTML from Cross Domain but the requested HTML contain image which is not loaded in response. Means the returned Cross Domain Requested HTML does not contain Image . Is there any way to load Image also?????Airtight
Images, CSS and external javascript can be referenced from another origin, thus, in the response you can go over the HTML string and replace the src of external resourcesMitchmitchael
hi jherax I used whateverorigin to get a html page (only way worked for me, used yql, google etc) but non english characters are strange. tried to encode data.contents but not helpedQuarterhour
@Quarterhour you may specify some ajax options to the requested resource, for example you can specify the contentType before making the ajax call. i.e. $.ajaxSetup({ scriptCharset: "utf-8" , contentType: "application/json; charset=utf-8"}); then you can make the ajax call with $.getJSON()Mitchmitchael
Hi @jherax. I've the exact same question, as hitesh question. But I fail to understand your answer. Could you please explain a bit more with an example maybe, in comment or edit your main answer. ThanksMicrofiche
Hello @Miru, as the title says: "Loading cross domain html page with jQuery AJAX", I answered to the title by providing some examples using a proxy to perform cross-domain requests. Also, in response to the wording of the question, I provided some links to make cross-domain requests using JSONP with YQL. I invite you to read the links, they are very useful.Mitchmitchael
I extended the answer, by adding more links and examples related to CORS proxy servers.Mitchmitchael
This is rad! Is there any way to load the HTML of a cross domain page that uses Ajax or some other method to finish loading its content? I keep getting the HTML of the cross domain page as it first loads, not the HTML of the page a second or two later, which is what I want. For example, how could one grab the HTML of table.referrals (after "Referral Amounts and Ride Requirements") at lyft.com/drive/help/article/1859265? Thanks!Serpens
For getting a portion of the response, if you receive a HTML string, you can parse the response to jQuery object, and then apply a filter (selector), eg: console.log(data); $(data).find('#title-1') or, if you receive a response without a root element, then use filter, e.g: $(data).filter('#title-1')Mitchmitchael
Ended up using the CORS Anywhere method with the $.ajaxPrefilter and it worked great. Many thanks!Thruway
God bless you @jherax. After spending a week, searching for the CORS issue day and night, i finally found your solution, it instantly worked. Its was like digital magic. Thanks a ton!!!Tare
It is good to know that after years that post was published, it still working!! :+1:Mitchmitchael
Do not use CORS Proxy - appears to be a virus website now.Giantess
K
25

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/

Kutuzov answered 3/8, 2014 at 16:30 Comment(4)
As far as I'm concerned, this plugin has never worked. It doesn't do anything on Chrome.Gablet
How can I authenticate to the server?Luiseluiza
works great! The API I'm using supports neither JSONP nor CORS so this is the only thing that worked. Thanks a lot!Curative
jQuery's crossOrigin option certainly does not do anything to mitigate same-origin policies. I'd delete this answer if I couldStatus
S
13

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.

Susannesusceptibility answered 21/2, 2013 at 15:5 Comment(0)
K
7

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");
}
Kolnick answered 17/9, 2017 at 22:8 Comment(2)
I'm wondering where $_SERVER['HTTP_ORIGIN'] is coming from. I couldn't find it in the PHP documentation or anywhere else.Logic
Hmm, it seems that it is populated only with AJAX requests. Anyhow, thanks for the answer.Logic
P
0

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.

Penance answered 18/5, 2016 at 10:46 Comment(0)
N
0

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

Nerta answered 22/6, 2016 at 12:44 Comment(0)
W
0

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>
Wallywalnut answered 26/1, 2019 at 7:12 Comment(0)
T
-2

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>
Totally answered 1/6, 2016 at 23:23 Comment(2)
This does not answer the question in any way.Fatwitted
@Fatwitted i've finally written answer.Totally
I
-7

Figured it out. Used this instead.

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');
Intercontinental answered 16/6, 2015 at 12:45 Comment(1)
The code you used there is irrelevant. What matters is the server side CORS headers.Frit

© 2022 - 2024 — McMap. All rights reserved.