Dodanie obsługi CORS do serwera proxy interfejsu API

Przeglądasz dokumentację Apigee Edge.
Otwórz dokumentację Apigee X.
Informacje

CORS (Udostępnianie zasobów między domenami) to standardowy mechanizm, który pozwala wywołaniom JavaScriptu XMLHttpRequest (XHR) wykonywanych na stronie internetowej interakcję z zasobami z domen innych niż źródłowe. CORS to powszechnie zaimplementowane rozwiązanie dotyczące zasady tego samego pochodzenia, które jest egzekwowane przez wszystkie przeglądarki. Jeśli na przykład wywołasz interfejs XHR API Twittera z kodu JavaScript wykonanego w przeglądarce, nie uda się. Dzieje się tak, ponieważ domena udostępniająca stronę w przeglądarce różni się od domeny obsługującej interfejs Twitter API. CORS rozwiązuje ten problem, umożliwiając serwerom wyrażenie zgody na udostępnianie zasobów między domenami.

Film: obejrzyj krótki film, aby dowiedzieć się, jak włączyć CORS na serwerze proxy interfejsu API.

Typowe przypadki użycia CORS

Poniższy kod JQuery wywołuje fikcyjną usługę docelową. Jeśli wywołanie zostanie wykonane w kontekście przeglądarki (strony internetowej), nie powiedzie się z powodu zasady dotyczącej tego samego źródła:

<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>

Jednym z rozwiązań tego problemu jest utworzenie serwera proxy Apigee API, który będzie wywoływał interfejs API usługi na zapleczu. Pamiętaj, że Edge znajduje się między klientem (w tym przypadku przeglądarką) a interfejsem API backendu (usługą). Serwer proxy interfejsu API jest wykonywany na serwerze, a nie w przeglądarce, dlatego może wywołać tę usługę. Następnie musisz tylko dołączyć nagłówki CORS do odpowiedzi z docelowym punktem końcowym. Jeśli przeglądarka obsługuje CORS, te nagłówki sygnalizują przeglądarce, że można złagodzić jej zasadę dotyczącą tej samej domeny, co pozwoli na pomyślne wywołanie interfejsu API z innych domen.

Po utworzeniu serwera proxy z obsługą CORS możesz wywołać URL serwera proxy interfejsu API zamiast usługi backendu w kodzie po stronie klienta. Na przykład:

<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>

Dołączono zasadę Add CORS do nowego serwera proxy interfejsu API

Możesz dodać obsługę CORS do serwera proxy interfejsu API, dołączając do niego podczas jego tworzenia zasadę „Dodaj CORS”. Aby dodać tę zasadę, zaznacz pole wyboru Dodaj nagłówki CORS na stronie Zabezpieczenia w kreatorze tworzenia serwera proxy.

Gdy zaznaczysz to pole wyboru, zasada Dodaj CORS zostanie automatycznie dodana do systemu i dołączona do wstępnego przepływu odpowiedzi elementu TargetEndpoint, jak pokazano na tym ilustracji:

Dodaj zasadę CORS dodaną do nawigatora w sekcji Zasady i dołączoną do wstępnego przepływu odpowiedzi TargetEndpoint w prawej części

Zasada Add CORS jest zaimplementowana jako zasada AssignMessage, która dodaje odpowiednie nagłówki do odpowiedzi. Zasadniczo nagłówki informują przeglądarkę, którym źródłom udostępnia swoje zasoby, jakie metody akceptuje itd. Więcej informacji o tych nagłówkach CORS znajdziesz w rekomendacji W3C dotyczącej udostępniania zasobów między serwerami.

Należy zmodyfikować zasady w następujący sposób:

  • Dodaj nagłówki content-type i authorization (wymagane do obsługi podstawowego uwierzytelniania lub protokołu OAuth2) do nagłówka Access-Control-Allow-Headers, jak pokazano w poniższym fragmencie kodu.
  • W przypadku uwierzytelniania OAuth2 konieczne może być wykonanie czynności w celu skorygowania działania niezgodnego z RFC.
  • Do ustawiania nagłówków CORS zamiast <Add> zalecamy używanie <Set>, jak pokazano we fragmencie poniżej. Jeśli używasz już nagłówka <Add>, pojawi się następujący błąd:Access-Control-Allow-Origin

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

    Więcej informacji znajdziesz w sekcji Błąd CORS : nagłówek zawiera wiele wartości „*, *”, ale dopuszczana jest tylko jedna z nich.

<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>

Dodawanie nagłówków CORS do istniejącego serwera proxy

Musisz ręcznie utworzyć nową zasadę przypisywania wiadomości i skopiować do niej kod zasady dodawania CORS wymienionej w poprzedniej sekcji. Następnie dołącz zasadę do wstępnego przepływu odpowiedzi docelowego punktu końcowego serwera proxy interfejsu API. W razie potrzeby możesz modyfikować wartości nagłówków. Więcej informacji o tworzeniu i dołączaniu zasad znajdziesz w artykule Co to jest zasada?.

Obsługa żądań wstępnych CORS

Proces wstępny CORS odnosi się do wysyłania żądania do serwera w celu sprawdzenia, czy obsługuje CORS. Typowe odpowiedzi procesu wstępnego obejmują informacje o tym, z których źródeł serwer akceptuje żądania CORS, a także listę metod HTTP obsługiwanych w przypadku żądań CORS, nagłówki, których można użyć w ramach żądania zasobu, maksymalny czas przechowywania odpowiedzi w pamięci podręcznej, itp. Jeśli usługa nie wskazuje obsługi CORS lub nie chce akceptować żądań z innych domen ze źródła klienta, egzekwowana będzie zasada przeglądarki z innych domen, a wszystkie żądania między domenami kierowane do klienta w celu interakcji z zasobami hostowanymi na tym serwerze zakończą się niepowodzeniem.

Zwykle żądania procesów wstępnych CORS są wykonywane przy użyciu metody HTTP OPTIONS. Gdy serwer obsługujący CORS otrzymuje żądanie OPTIONS, zwraca do klienta zestaw nagłówków CORS, które wskazują jego poziom obsługi CORS. Dzięki temu uzgadnianie połączenia klient wie, czego może żądać z domeny innej niż źródłowa.

Więcej informacji na temat procesów wstępnych znajdziesz w artykule Zalecenie W3C dotyczące udostępniania zasobów między serwerami zewnętrznymi (w języku angielskim). Istnieje też wiele blogów i artykułów na temat CORS, z którymi możesz się zapoznać.

Apigee nie zawiera gotowego rozwiązania procesu wstępnego CORS, ale można je wdrożyć w sposób opisany w tej sekcji. Celem jest, aby serwer proxy oceniał żądanie OPTIONS w przepływie warunkowym. Serwer proxy może następnie wysłać do klienta odpowiednią odpowiedź.

Przyjrzyjmy się przykładowym przepływom, a następnie omów części, które obsługują żądanie wstępne:

<?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>

Najważniejsze elementy tego punktu końcowego to:

  • Reguła trasy jest tworzona z wartością docelową o wartości NULL z warunkiem żądania OPTIONS. Nie określono elementu TargetEndpoint. Jeśli zostanie odebrane żądanie OPTIONS, a nagłówki żądania Origin i Access-Control-Request-Method nie mają wartości null, serwer proxy natychmiast zwróci nagłówki CORS w odpowiedzi klienta (przez pominięcie rzeczywistego domyślnego miejsca docelowego backendu). Szczegółowe informacje na temat warunków przepływu i reguły trasy znajdziesz w artykule Warunki ze zmiennymi przepływu.

    <RouteRule name="NoRoute">
        <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition>
    </RouteRule>
    
  • Tworzony jest przepływ OptionPreFlight, który dodaje do procesu zasadę Add CORS zawierającą nagłówki CORS, jeśli zostanie odebrane żądanie OPTIONS, a nagłówki żądania Origin i Access-Control-Request-Method nie mają wartości null.

     <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>
    

Korzystanie z przykładowego rozwiązania CORS

Przykładowe rozwiązanie CORS, zaimplementowane w ramach przepływu współdzielonego, jest dostępne w serwisie GitHub. Zaimportuj pakiet wspólnego procesu do swojego środowiska i dołącz go za pomocą punktów zaczepienia przepływów lub bezpośrednio do przepływów serwera proxy interfejsu API. Szczegółowe informacje znajdziesz w pliku CORS-Shared-FLow README dołączonym do przykładu.