Вы просматриваете документацию Apigee Edge .
Перейдите в документацию Apigee X.info
CORS (Cross-origin resource sharing) — это стандартный механизм, позволяющий вызовам JavaScript XMLHttpRequest (XHR), выполняемым на веб-странице, взаимодействовать с ресурсами из доменов, не являющихся доменами вашего источника. CORS — это широко распространенное решение проблемы « политики одного источника », которая применяется всеми браузерами. Например, если вы выполняете вызов XHR к API Twitter из кода JavaScript, работающего в вашем браузере, вызов завершится неудачей. Это происходит потому, что домен, обслуживающий страницу в вашем браузере, не совпадает с доменом, обслуживающим API Twitter. CORS решает эту проблему, позволяя серверам «добровольно» включать функцию совместного использования ресурсов между источниками, если они этого хотят.
Видео: Посмотрите короткое видео, чтобы узнать, как включить CORS для API-прокси.
Типичный сценарий использования CORS
Приведенный ниже код jQuery вызывает фиктивный целевой сервис. Если его выполнить в контексте браузера (веб-страницы), вызов завершится ошибкой из-за политики ограничения доступа из одного источника:
<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>
Одно из решений этой проблемы — создание прокси-сервера API Apigee, который вызывает API сервиса на бэкэнде. Помните, что Edge находится между клиентом (в данном случае браузером) и бэкэнд-API (сервисом). Поскольку прокси-сервер API выполняется на сервере, а не в браузере, он может успешно вызывать сервис. Затем все, что вам нужно сделать, это добавить заголовки CORS к ответу TargetEndpoint. Пока браузер поддерживает CORS, эти заголовки сигнализируют браузеру о том, что можно «ослабить» политику одного источника, что позволяет успешно выполнить вызов API из другого источника.
После создания прокси-сервера с поддержкой CORS вы можете вызывать URL-адрес API-прокси вместо серверной службы в клиентском коде. Например:
<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>
Добавление политики CORS к новому API-прокси
Добавить поддержку CORS к API-прокси можно, прикрепив к нему политику "Добавить CORS" при его создании. Для этого установите флажок " Добавить заголовки CORS" на странице "Безопасность" мастера создания прокси.
При установке этого флажка в систему автоматически добавляется политика под названием «Добавить CORS», которая затем прикрепляется к предварительному потоку ответа TargetEndpoint, как показано на следующем рисунке:

Политика добавления CORS реализована как политика AssignMessage , которая добавляет соответствующие заголовки к ответу. По сути, заголовки сообщают браузеру, с какими источниками он будет делиться своими ресурсами, какие методы он принимает и так далее. Подробнее об этих заголовках CORS можно прочитать в рекомендации W3C по совместному использованию ресурсов между источниками (Cross-Origin Resource Sharing) .
Вам следует изменить политику следующим образом:
- Добавьте заголовки
content-typeиauthorization(необходимые для поддержки базовой аутентификации или OAuth2) в заголовокAccess-Control-Allow-Headers, как показано в приведенном ниже фрагменте кода. - Для аутентификации OAuth2 может потребоваться предпринять шаги для исправления поведения, не соответствующего RFC .
- Рекомендуется использовать
<Set>для установки заголовков CORS вместо<Add>, как показано в приведенном ниже фрагменте. При использовании<Add>, если заголовокAccess-Control-Allow-Originуже существует, вы получите следующую ошибку:The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.Для получения дополнительной информации см. ошибку CORS: заголовок содержит несколько значений '*, *', но допускается только одно .
<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>
Добавление заголовков CORS к существующему прокси-серверу
Вам необходимо вручную создать новую политику назначения сообщений и скопировать в нее код политики добавления CORS, указанный в предыдущем разделе. Затем прикрепите политику к предварительному потоку ответа целевой конечной точки API-прокси. При необходимости вы можете изменить значения заголовков. Дополнительную информацию о создании и прикреплении политик см. в разделе «Что такое политика?» .
Обработка запросов CORS перед проверкой
Предварительная проверка CORS (CORS preflight) — это отправка запроса на сервер для проверки поддержки CORS. Типичные ответы предварительной проверки включают в себя информацию о том, с каких источников сервер будет принимать запросы CORS, список поддерживаемых методов HTTP для запросов CORS, заголовки, которые могут использоваться в запросе ресурса, максимальное время кэширования ответа предварительной проверки и другие данные. Если сервис не указывает на поддержку CORS или не желает принимать междоменные запросы от клиента, будет применена политика междоменных запросов браузера, и любые междоменные запросы, сделанные клиентом для взаимодействия с ресурсами, размещенными на этом сервере, будут отклонены.
Как правило, предварительные запросы CORS выполняются с использованием метода HTTP OPTIONS. Когда сервер, поддерживающий CORS, получает запрос OPTIONS, он возвращает клиенту набор заголовков CORS, указывающих на уровень поддержки CORS. В результате этого рукопожатия клиент знает, какие запросы ему разрешено отправлять с домена, не являющегося исходным.
Для получения дополнительной информации о предварительной проверке (preflight) обратитесь к рекомендациям W3C по обмену ресурсами между источниками (Cross-Origin Resource Sharing, CORS). Кроме того, существует множество блогов и статей о CORS, к которым вы можете обратиться.
Apigee не включает в себя готовое решение для предварительной проверки CORS, но его можно реализовать, как описано в этом разделе. Цель состоит в том, чтобы прокси-сервер оценивал запрос OPTIONS в условном потоке. Затем прокси-сервер может отправить соответствующий ответ клиенту.
Рассмотрим примерный алгоритм действий, а затем обсудим части, обрабатывающие предварительный запрос:
<?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>Основные компоненты данного ProxyEndpoint следующие:
- Создается правило маршрутизации (RouteRule) для целевого объекта со значением NULL и условием для запроса OPTIONS. Обратите внимание, что TargetEndpoint не указан. Если запрос OPTIONS получен и заголовки запроса Origin и Access-Control-Request-Method не равны NULL, прокси-сервер немедленно возвращает заголовки CORS в ответе клиенту (обходя фактический целевой объект «бэкэнда» по умолчанию). Подробную информацию об условиях потока и правиле маршрутизации см. в разделе «Условия с переменными потока ».
<RouteRule name="NoRoute"> <Condition>request.verb == "OPTIONS" AND request.header.origin != null AND request.header.Access-Control-Request-Method != null</Condition> </RouteRule> - Создается поток OptionsPreFlight, который добавляет политику Add CORS, содержащую заголовки CORS, в поток, если получен запрос OPTIONS и заголовки запроса Origin и Access-Control-Request-Method не являются пустыми.
<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>
Используя образец раствора CORS
Пример решения CORS, реализованного в виде общего потока, доступен на GitHub . Импортируйте пакет общего потока в свою среду и подключите его с помощью хуков потока или напрямую к потокам прокси API. Подробности см. в файле README CORS-Shared-FLow, прилагаемом к примеру.