Dodanie obsługi CORS do serwera proxy interfejsu API

Wyświetlasz dokumentację Apigee Edge.
Przejdź do dokumentacji Apigee X.
info

CORS (Cross-origin resource sharing) to standardowy mechanizm, który umożliwia wywoływanie JavaScriptu XMLHttpRequest (XHR) wykonywane na stronie internetowej w celu interakcji z zasobami ze współdzielonych domen. CORS to powszechnie stosowane rozwiązanie problemu "zasady dotyczące tego samego źródła", które są egzekwowane przez wszystkie przeglądarki. Jeśli na przykład wywołasz interfejs Twitter API za pomocą kodu JavaScript działającego w przeglądarce, wywołanie się nie powiedzie. Dzieje się tak, ponieważ domena, która wyświetla stronę w przeglądarce, nie jest taka sama jak domena, która obsługuje interfejs Twitter API. CORS rozwiązuje ten problem, umożliwiając serwerom „rezygnację” z udostępniania zasobów z innych domen.

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

Typowy przypadek użycia CORS

Poniższy kod JQuery wywołuje fikcyjną usługę docelową. Jeśli zostanie wykonany w kontekście przeglądarki (strony internetowej), wywołanie się nie powiedzie 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 interfejsu Apigee API, który wywołuje interfejs API usługi w backendzie. Pamiętaj, że Edge znajduje się między klientem (w tym przypadku przeglądarką) a interfejsem API backendu (usługą). Ponieważ serwer proxy interfejsu API działa na serwerze, a nie w przeglądarce, to jest w stanie pomyślnie wywołać usługę. Następnie wystarczy dołączyć nagłówki CORS do odpowiedzi TargetEndpoint. Jeśli przeglądarka obsługuje CORS, te nagłówki informują ją, że może „złagodzić” zasadę dotyczącą tego samego źródła, co umożliwi pomyślne wykonanie wywołania interfejsu API ze współdzieleniem.

Po utworzeniu serwera proxy z obsługą CORS możesz wywołać adres 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łączanie zasady „Dodaj CORS” do nowego serwera proxy interfejsu API

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

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

Zasady CORS dodane do nawigatora w sekcji Zasady i dołączone do wstępnego przepływu odpowiedzi TargetEndpoint w panelu po prawej stronie

Zasada Dodaj CORS jest implementowana jako zasada AssignMessage, która dodaje odpowiednie nagłówki do odpowiedzi. Zasadniczo nagłówki informują przeglądarkę, z jakimi źródłami będzie 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 z innych domen.

Zmień zasadę w ten sposób:

  • Dodaj nagłówki content-type i authorization (wymagane do obsługi uwierzytelniania podstawowego lub OAuth2) do nagłówka Access-Control-Allow-Headers, jak pokazano w poniższym fragmencie kodu.
  • W przypadku uwierzytelniania OAuth2 może być konieczne podjęcie działań w celu skorygowania zachowania niezgodnego z RFC.
  • Zalecamy używanie <Set> do ustawiania nagłówków CORS zamiast <Add>, jak pokazano w poniższym fragmencie. Jeśli używasz <Add>, a nagłówek Access-Control-Allow-Origin już istnieje, otrzymasz ten błąd:

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

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

<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ę Assign Message i skopiować do niej kod zasady Dodaj CORS wymienionej w poprzedniej sekcji. Następnie dołącz zasadę do przepływu wstępnego odpowiedzi TargetEndpoint serwera proxy interfejsu API. W razie potrzeby możesz zmodyfikować wartości nagłówka. Więcej informacji o tworzeniu i dołączaniu zasad znajdziesz w artykule Co to jest zasada?.

Obsługa żądań wstępnych CORS

Wstępne żądanie CORS to wysłanie żądania do serwera w celu sprawdzenia, czy obsługuje on CORS. Typowe odpowiedzi wstępne obejmują informacje o tym, z jakich źródeł serwer będzie akceptować żądania CORS z, listę metod HTTP obsługiwanych w przypadku żądań CORS, nagłówki, które mogą być używane jako część żądania zasobu, maksymalny czas przechowywania odpowiedzi wstępnej w pamięci podręcznej i inne. Jeśli usługa nie wskazuje obsługi CORS lub nie chce akceptować żądań współdzielenia od źródła klienta, zostanie zastosowana zasada współdzielenia przeglądarki, a wszystkie żądania współdzielenia wysyłane przez klienta w celu interakcji z zasobami hostowanymi na tym serwerze nie powiodą się.

Zazwyczaj wstępne żądania CORS są wysyłane za pomocą metody HTTP OPTIONS. Gdy serwer obsługujący CORS otrzyma żądanie OPTIONS, zwraca do klienta zestaw nagłówków CORS, które wskazują poziom obsługi CORS. W wyniku tego uzgadniania klient wie, o co może poprosić w domenie innej niż źródłowa.

Więcej informacji o procesie wstępnym znajdziesz w rekomendacji W3C dotyczącej udostępniania zasobów z innych domen. Istnieje też wiele blogów i artykułów na temat CORS, z których możesz skorzystać.

Apigee nie zawiera gotowego rozwiązania wstępnego żądania CORS, ale można je zaimplementować zgodnie z opisem w tej sekcji. Celem jest, aby serwer proxy oceniał żądanie OPTIONS w przepływie warunkowym. Serwer proxy może wtedy wysłać odpowiednią odpowiedź do klienta.

Przyjrzyjmy się przykładowemu przepływowi, a następnie omówmy 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>

Kluczowe części tego ProxyEndpoint są te:

  • Tworzona jest reguła RouteRule do celu NULL z warunkiem dla żądania OPTIONS. Pamiętaj, że nie określono TargetEndpoint. Jeśli zostanie odebrane żądanie OPTIONS, a nagłówki żądania Origin i Access-Control-Request-Method nie są puste, serwer proxy natychmiast zwraca nagłówki CORS w odpowiedzi do klienta (pomijając rzeczywisty domyślny cel "backend"). Szczegółowe informacje o warunkach przepływu i regule RouteRule znajdziesz w artykule Warunki z 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 OptionsPreFlight, który dodaje do przepływu zasadę Dodaj CORS zawierającą nagłówki CORS , jeśli zostanie odebrane żądanie OPTIONS, a nagłówki żądania Origin i Access-Control-Request-Method nie są puste.

     <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 jako współdzielony przepływ jest dostępne na GitHub. Zaimportuj pakiet współdzielonego przepływu do swojego środowiska i dołącz go za pomocą haków przepływu 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.