Aggiunta del supporto CORS a un proxy API

Stai visualizzando la documentazione di Apigee Edge.
Vai alla sezione Documentazione di Apigee X.
Informazioni

CORS (condivisione delle risorse tra origini) è un meccanismo standard che consente a JavaScript Chiamate XMLHttpRequest (XHR) eseguite in una pagina web per interagire con risorse da origini diverse domini. CORS è una soluzione comunemente implementata per il "criterio della stessa origine" applicato da tutti i browser. Ad esempio, se effettui una chiamata XHR all'API Twitter dal codice JavaScript in esecuzione nel browser, la chiamata non andrà a buon fine. Questo perché il dominio che pubblica la pagina il tuo browser non corrisponde al dominio che gestisce l'API Twitter. CORS offre una soluzione questo problema consentendo ai server di "attivare" se vuole fornire una risorsa multiorigine condivisione.

Video: guarda un breve video per scoprire come attivare CORS su un proxy API.

Caso d'uso tipico di CORS

Il codice JQuery riportato di seguito chiama un servizio di destinazione fittizio. Se eseguita dall'interno contesto di un browser (una pagina web), la chiamata non andrà a buon fine a causa del criterio della stessa origine:

<script>
var url = "http://service.example.com";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This is where we end up!
            }
    });
  });
});
</script>

Una soluzione a questo problema è creare un proxy API Apigee che chiami l'API di servizio su il backend. Ricorda che Edge si trova tra il client (in questo caso un browser) e il backend API (il servizio). Poiché il proxy API viene eseguito sul server, non in un browser, è in grado di chiamare il servizio correttamente. Poi, tutto quello che devi fare è collegare le intestazioni CORS alla risposta TargetEndpoint. Se il browser supporta CORS, queste intestazioni indicano al browser che va bene "rilassarsi" del suo criterio della stessa origine, la chiamata API multiorigine.

Una volta creato il proxy con supporto CORS, puoi chiamare l'URL del proxy API anziché la nel tuo codice lato client. Ad esempio:

<script>
var url = "http://myorg-test.apigee.net/v1/example";
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
        type:"GET",
        url:url,
        async:true,
        dataType: "json",
           success: function(json) {
              // Parse the response.
              // Do other things.
           },
           error: function(xhr, status, err) {
              // This time, we do not end up here!
            }
    });
  });
});
</script>

Collegamento di un criterio Aggiungi CORS a una nuova API proxy

Puoi aggiungere il supporto CORS a un proxy API collegando un link "Aggiungi CORS" al proxy API quando lo crei. Per aggiungere questo criterio, seleziona la casella di controllo Aggiungi intestazioni CORS in alla pagina Sicurezza della procedura guidata Crea un proxy.

Quando selezioni questa casella di controllo, al sistema viene aggiunto automaticamente un criterio denominato Aggiungi CORS e collegato al preflusso di risposta TargetEndpoint, come mostrato nella figura seguente:

Aggiungi criterio CORS aggiunto al navigatore nella sezione Criteri e collegato al preflusso di risposta di TargetEndpoint nella panoramica a destra

Il criterio Add CORS è implementato come criterioAssignMessage, che aggiunge le intestazioni appropriate alla risposta. Fondamentalmente, le intestazioni permettono al browser di sapere con quali origini condividerà le sue risorse, i metodi che accetta e così via. Per saperne di più su queste intestazioni CORS, consulta il Consiglio di W3C per la condivisione delle risorse tra origini.

Ti consigliamo di modificare la norma nel seguente modo:

  • Aggiungi le intestazioni content-type e authorization (necessarie per supportare l'autenticazione di base o OAuth2) all'intestazione Access-Control-Allow-Headers, come mostrato nell'estratto del codice di seguito.
  • Per l'autenticazione OAuth2, potrebbe essere necessario adottare alcune misure per correggere il comportamento non conforme alla specifica RFC.
  • Ti consigliamo di utilizzare <Set> per impostare le intestazioni CORS anziché <Add>, come mostrato nell'estratto di seguito. Quando utilizzi <Add>, se l'intestazione Access-Control-Allow-Origin esiste già, viene visualizzato il seguente errore:

    The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

    Per ulteriori informazioni, vedi Errore CORS : l'intestazione contiene più valori "*, *", ma ne è consentito solo uno.

<AssignMessage async="false" continueOnError="false" enabled="true" name="add-cors">
    <DisplayName>Add CORS</DisplayName>
    <FaultRules/>
    <Properties/>
    <Set>
        <Headers>
            <Header name="Access-Control-Allow-Origin">{request.header.origin}</Header>
            <Header name="Access-Control-Allow-Headers">origin, x-requested-with, accept, content-type, authorization</Header>
            <Header name="Access-Control-Max-Age">3628800</Header>
            <Header name="Access-Control-Allow-Methods">GET, PUT, POST, DELETE</Header>
        </Headers>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

Aggiunta di intestazioni CORS a un proxy esistente

Devi creare manualmente un nuovo criterio Assegna messaggio e copiare il codice per Aggiungi CORS elencati nella sezione precedente. Quindi, collega il criterio al preflusso della risposta il TargetEndpoint del proxy API. Se necessario, puoi modificare i valori dell'intestazione. Per ulteriori informazioni informazioni sulla creazione e sul collegamento dei criteri, consulta la sezione Che cos'è una norma?.

Gestione di CORS richieste preflight

Con preflight CORS si intende l'invio di una richiesta a un server per verificare se supporta CORS. Le risposte preflight tipiche includono le origini che il server accetta CORS richieste da, un elenco di metodi HTTP supportati per le richieste CORS, intestazioni che possono essere se viene utilizzata nell'ambito della richiesta di risorsa, il tempo massimo per la risposta preflight verrà memorizzato nella cache e altri. Se il servizio non indica il supporto CORS o non vuole accettare multiorigine richieste dall'origine del client, il criterio multiorigine del browser verrà applicato in modo forzato Qualsiasi richiesta interdominio effettuata dal client per interagire con le risorse ospitate su tale server non riuscirà.

In genere, le richieste preflight CORS vengono effettuate con il metodo HTTP OPTIONS. Quando un server supporta CORS riceve una richiesta OPTIONS, restituisce un set di intestazioni CORS al client che indicare il livello di supporto di CORS. Come risultato di questo handshake, il client sa di cosa si tratta può richiedere dal dominio non di origine.

Per ulteriori informazioni sull'elaborazione preflight, consulta il consiglio del W3C per la condivisione delle risorse tra origini. Sono presenti Inoltre, numerosi blog e articoli su CORS a cui puoi fare riferimento.

Apigee non include una soluzione preflight CORS pronta all'uso, ma è possibile come descritto in questa sezione. L'obiettivo è che il proxy valuti un OPTIONS una richiesta in un flusso condizionale. Il proxy può quindi inviare una risposta appropriata al di alto profilo.

Esaminiamo un flusso di esempio e poi parliamo delle parti che gestiscono la richiesta preflight:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <Description/>
    <Flows>
        <Flow name="OptionsPreFlight">
            <Request/>
            <Response>
                <Step>
                    <Name>add-cors</Name>
                </Step>
            </Response>
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
        </Flow>
    </Flows>

    <PreFlow name="PreFlow">
        <Request/>
        <Response/>

    </PreFlow>
    <HTTPProxyConnection>
        <BasePath>/v1/cnc</BasePath>
        <VirtualHost>default</VirtualHost>
        <VirtualHost>secure</VirtualHost>
    </HTTPProxyConnection>
    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
   </RouteRule>
   <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
</ProxyEndpoint>

Le parti principali di questo ProxyEndpoint sono le seguenti:

  • Una RouteRule viene creata verso una destinazione NULL con una condizione per la richiesta OPTIONS. Tieni presente che non è specificato nessun TargetEndpoint. Se la richiesta OPTIONS viene ricevuta e i valori di origine e Le intestazioni delle richieste Access-Control-Request-Method non sono nulle, il proxy restituisce immediatamente il valore Intestazioni CORS in una risposta al client (ignorando l'effettivo target di "backend" predefinito). Per maggiori dettagli sulle condizioni di flusso e RouteRule, consulta Condizioni con variabili di flusso.

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • Viene creato un flusso OptionsPreFlight che aggiunge un criterio Add CORS, contenente il valore CORS intestazioni, al flusso se viene ricevuta una richiesta OPTIONS e i campi Origine e Le intestazioni delle richieste Access-Control-Request-Method non sono nulle.

     <Flow name="OptionsPreFlight">
                <Request/>
                <Response>
                    <Step>
                        <Name>add-cors</Name>
                    </Step>
                </Response>
            <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
     </Flow>
    

Utilizzo della soluzione CORS di esempio

Su GitHub è disponibile una soluzione CORS di esempio, implementata come flusso condiviso. Importa il bundle di flusso condiviso nel tuo ambiente e collegalo utilizzando gli hook di flusso o direttamente ai flussi proxy API. Per maggiori dettagli, consulta File CORS-Shared-FLow README fornito con l'esempio.