Caricamento endpoint tra domini con AJAX


131

Sto cercando di caricare una pagina HTML tra domini utilizzando AJAX ma a meno che dataType sia "jsonp" non riesco a ottenere una risposta. Comunque usando jsonp il browser si aspetta un tipo mime di script ma sta ricevendo "text / html".

Il mio codice per la richiesta è:

$.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 );
});

Esiste un modo per evitare di usare jsonp per la richiesta? Ho già provato a utilizzare il parametro crossDomain ma non ha funzionato.

In caso contrario, c'è modo di ricevere il contenuto html in jsonp? Attualmente la console dice "imprevisto <" nella risposta jsonp.


Ho risolto il problema creando un proxy.php come spiegato qui scode7.blogspot.com/2019/11/…
CodeDezk

Risposte:


235

jQuery Ajax Note

  • A causa delle restrizioni di sicurezza del browser, la maggior parte delle richieste Ajax sono soggette alla stessa politica di origine ; la richiesta non può recuperare correttamente i dati da un dominio, sottodominio, porta o protocollo diversi.
  • Le richieste di script e JSONP non sono soggette alle stesse restrizioni della politica di origine.

Esistono alcuni modi per superare la barriera interdominio :

Ci sono alcuni plugin che aiutano con le richieste tra domini :

Dritta!

Il modo migliore per ovviare a questo problema è creare il proprio proxy nel back-end, in modo che il proxy punti ai servizi in altri domini, perché nel back-end non esiste la stessa restrizione della politica di origine . Ma se non riesci a farlo nel back-end, presta attenzione ai seguenti suggerimenti.


Avvertimento!

L'uso di proxy di terze parti non è una pratica sicura, perché possono tenere traccia dei tuoi dati, quindi possono essere utilizzati con informazioni pubbliche, ma mai con dati privati.


Gli esempi di codice mostrati di seguito usano jQuery.get () e jQuery.getJSON () , entrambi sono metodi abbreviati di jQuery.ajax ()


CORS Ovunque

CORS Anywhere è un proxy node.js che aggiunge le intestazioni CORS alla richiesta proxy.
Per utilizzare l'API, basta aggiungere il prefisso all'URL con l'URL dell'API. (Supporta https : vedi repository github )

Se si desidera abilitare automaticamente le richieste tra domini quando necessario, utilizzare il frammento seguente:

$.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);
});


Qualunque sia l'origine

Qualunque sia l'origine è un accesso jsonp interdominio . Questa è un'alternativa open source a anyorigin.com .

Per recuperare i dati da google.com, puoi utilizzare questo frammento:

// 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);
});


Proxy CORS

CORS Proxy è un semplice proxy node.js per abilitare la richiesta CORS per qualsiasi sito Web. Consente al codice javascript sul tuo sito di accedere a risorse su altri domini che sarebbero normalmente bloccati a causa della stessa politica di origine.

Come funziona? CORS Proxy sfrutta la condivisione delle risorse tra le origini, che è stata aggiunta insieme a HTML 5. I server possono specificare che desiderano che i browser consentano ad altri siti Web di richiedere risorse che ospitano. CORS Proxy è semplicemente un proxy HTTP che aggiunge un'intestazione alle risposte dicendo "chiunque può richiederlo".

Questo è un altro modo per raggiungere l'obiettivo (vedi www.corsproxy.com ). Tutto quello che devi fare è rimuovere http: // e www. dall'URL inviato in proxy e anteporre l'URL conwww.corsproxy.com/

$.get(
    'http://www.corsproxy.com/' +
    'en.wikipedia.org/wiki/Cross-origin_resource_sharing',
    function (response) {
        console.log("> ", response);
        $("#viewer").html(response);
});


Browser proxy CORS

Recentemente ho trovato questo, che coinvolge varie utility di condivisione remota Cross Origin orientate alla sicurezza. Ma è una scatola nera con Flash come backend.

Puoi vederlo in azione qui: Browser proxy CORS
Ottieni il codice sorgente su GitHub: koto / cors-proxy-browser


4
Puoi anche distribuire la tua versione di qualunqueOrigin.org (o trasferire il codice per il tuo uso personale) da qui: github.com/ripper234/Whatever-Origin
EpicVoyage

1
Immagini, CSS e javascript esterni possono essere referenziati da un'altra origine, quindi nella risposta puoi andare oltre la stringa HTML e sostituire l'src di risorse esterne
jherax,

1
ciao jherax ho usato qualunque sia l'origine per ottenere una pagina html (solo per me ha funzionato, usato yql, google ecc.) ma i caratteri non inglesi sono strani. ha provato a codificare data.contents ma non ha aiutato
user217648

1
Ciao @Miru, come dice il titolo: "Caricamento della pagina html tra domini con jQuery AJAX", ho risposto al titolo fornendo alcuni esempi utilizzando un proxy per eseguire richieste tra domini. Inoltre, in risposta alla formulazione della domanda, ho fornito alcuni collegamenti per effettuare richieste tra domini utilizzando JSONP con YQL. Ti invito a leggere i link, sono molto utili.
jherax,

1
Alla fine ho usato il metodo CORS Anywhere con $.ajaxPrefiltere ha funzionato alla grande. Grazie molto!
Joshua Pinter,

24

Puoi usare Ajax-cross-origin un plugin jQuery. Con questo plugin usi jQuery.ajax()cross domain. Utilizza i servizi di Google per raggiungere questo obiettivo:

Il plug-in AJAX Cross Origin utilizza Google Apps Script come getter proxy jSON in cui jSONP non è implementato. Quando imposti l'opzione crossOrigin su true, il plug-in sostituisce l'URL originale con l'indirizzo dello script di Google Apps e lo invia come parametro url codificato. Lo script di Google Apps utilizza le risorse dei server di Google per ottenere i dati remoti e restituirli al client come JSONP.

È molto semplice da utilizzare:

    $.ajax({
        crossOrigin: true,
        url: url,
        success: function(data) {
            console.log(data);
        }
    });

Puoi leggere di più qui: http://www.ajax-cross-origin.com/


22
Per quanto mi riguarda, questo plugin non ha mai funzionato. Non fa nulla su Chrome.
Michael,

Come posso autenticarmi sul server?
Stataq

funziona alla grande! L'API che sto usando non supporta né JSONP né CORS, quindi questa è l'unica cosa che ha funzionato. Molte grazie!
JP Lew,

L' crossOriginopzione di jQuery certamente non fa nulla per mitigare le politiche sulla stessa origine. Eliminerei questa risposta se potessi
Phil

13

Se il sito esterno non supporta JSONP o CORS, l'unica opzione è utilizzare un proxy.

Crea uno script sul tuo server che richiede quel contenuto, quindi usa jQuery ajax per colpire lo script sul tuo server.


5

Metti questo nell'intestazione della tua pagina PHP e funzionerà senza API:

header('Access-Control-Allow-Origin: *'); //allow everybody  

o

header('Access-Control-Allow-Origin: http://codesheet.org'); //allow just one domain 

o

$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");
}

Mi chiedo da dove $_SERVER['HTTP_ORIGIN']venga. Non sono riuscito a trovarlo nella documentazione di PHP o altrove.
Zsolti,

Hmm, sembra che sia popolato solo con richieste AJAX. Comunque, grazie per la risposta.
Zsolti,

0

Sto pubblicando questo nel caso qualcuno dovesse affrontare lo stesso problema che sto affrontando in questo momento. Ho una stampante termica Zebra, dotata del server di stampa ZebraNet, che offre un'interfaccia utente basata su HTML per la modifica di più impostazioni, la visualizzazione dello stato corrente della stampante, ecc. Devo ottenere lo stato della stampante, che viene visualizzato in una di quelle pagine html, offerte dal server ZebraNet e, ad esempio, avvisa () un messaggio per l'utente nel browser. Ciò significa che devo prima ottenere quella pagina HTML in Javascript. Sebbene la stampante sia all'interno della LAN del PC dell'utente, quella stessa politica di originesta ancora fermamente sulla mia strada. Ho provato JSONP, ma il server restituisce html e non ho trovato un modo per modificarne la funzionalità (se potessi, avrei già impostato l'intestazione magica Access-control-allow-origin: *). Così ho deciso di scrivere una piccola app console in C #. Deve essere eseguito come amministratore per funzionare correttamente, altrimenti troll: D un'eccezione. Ecco un po 'di codice:

// 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();

Tutto ciò che l'utente deve fare è eseguire l'app console come amministratore. So che è troppo ... frustrante e complicato, ma è una sorta di soluzione al problema dei criteri di dominio nel caso in cui non sia possibile modificare il server in alcun modo.

modifica: da js faccio una semplice chiamata ajax:

$.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);
                }
            });

L'html della pagina richiesta viene restituito e archiviato nella variabile dati .


0

Per ottenere il modulo di dati dal sito esterno passando un proxy locale come suggerito da jherax è possibile creare una pagina php che recupera il contenuto dall'URL esterno corrispondente e che invia una richiesta get a quella pagina php.

var req = new XMLHttpRequest();
req.open('GET', 'http://localhost/get_url_content.php',false);
if(req.status == 200) {
   alert(req.responseText);
}

come proxy php puoi usare https://github.com/cowboy/php-simple-proxy


0

Al momento URLnon funziona, ma il tuo codice può essere aggiornato con questa soluzione funzionante:

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>


-2

È necessario il proxy CORS che inoltra la richiesta dal browser al servizio richiesto con le intestazioni CORS appropriate . L'elenco di tali servizi si trova nello snippet di codice di seguito. Puoi anche eseguire lo snippet di codice fornito per visualizzare il ping a tali servizi dalla tua posizione.

$('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>


11
Questo non risponde in alcun modo alla domanda.
0xc0de,

@ 0xc0de ho finalmente scritto la risposta.
Galeksandrp,

-7

Capito. Usato questo invece.

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');

Il codice che hai usato lì è irrilevante. Ciò che conta sono le intestazioni CORS lato server.
Quentin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.