Почему отправляется запрос OPTIONS и могу ли я его отключить?

Я строю веб-API. Я обнаружил, что всякий раз, когда я использую Chrome для POST, GET для моего API, всегда есть запрос OPTIONS, отправляемый перед реальным запросом, что довольно раздражает. В настоящее время я получаю сервер игнорировать любые запросы OPTIONS. Теперь мои вопросы: что хорошего в отправке запроса OPTIONS для удвоения нагрузки на сервер? Есть ли способ полностью запретить браузеру отправлять запросы OPTIONS?

306
29 апр. '15 в 23:37
источник поделиться
15 ответов

edit 2018-09-13: добавлены некоторые уточнения в отношении этого запроса перед полетом и как его избежать в конце этого ответа.

Запросы OPTIONS - это то, что мы называем pre-flight запросами при Cross-origin resource sharing (CORS).

Они необходимы, когда вы делаете запросы из разных источников в определенных ситуациях.

Этот предполетный запрос сделан некоторыми браузерами как мера безопасности, чтобы гарантировать, что выполняемый запрос является доверенным сервером. Это означает, что сервер понимает, что метод, источник и заголовки, отправляемые по запросу, безопасны для действий.

Ваш сервер не должен игнорировать, а обрабатывать эти запросы всякий раз, когда вы пытаетесь выполнить запросы из разных источников.

Хороший ресурс можно найти здесь http://enable-cors.org/

Чтобы справиться с этим, чтобы убедиться, что для любого пути с методом OPTIONS сервер отправляет ответ с этим заголовком

Access-Control-Allow-Origin: *

Это скажет браузеру, что сервер готов отвечать на запросы любого происхождения.

Для получения дополнительной информации о том, как добавить поддержку CORS на ваш сервер, смотрите следующую блок-схему

http://www.html5rocks.com/static/images/cors_server_flowchart.png

CORS Flowchart


редактировать 2018-09-13

Запрос CORS OPTIONS запускается только в некоторых случаях, как объяснено в документах MDN:

Некоторые запросы не запускают предварительную проверку CORS. В этой статье они называются "простыми запросами", хотя в спецификации Fetch (которая определяет CORS) этот термин не используется. Запрос, который не запускает предварительную проверку CORS - так называемый "простой запрос" - это запрос, который удовлетворяет всем следующим условиям:

Единственные допустимые методы:

  • ПОЛУЧИТЬ
  • ГОЛОВА
  • СООБЩЕНИЕ

Помимо заголовков, автоматически устанавливаемых пользовательским агентом (например, Connection, User-Agent или любым другим заголовком с именами, определенными в спецификации Fetch как "имя запрещенного заголовка"), единственными заголовками, которым разрешено быть вручную устанавливаются те, которые спецификация Fetch определяет как "заголовок запроса CORS-safelisted", а именно:

  • принимать
  • Accept-Language
  • Content-Language
  • Content-Type (но обратите внимание на дополнительные требования ниже)
  • DPR
  • Downlink
  • Сохранить данные
  • ВЭкран-Ширина
  • ширина

Единственные допустимые значения для заголовка Content-Type:

  • применение/х-WWW-форм-urlencoded
  • многочастному/форм-данных,
  • текст/обычный

Ни один прослушиватель событий не зарегистрирован ни для какого объекта XMLHttpRequestUpload, используемого в запросе; доступ к ним осуществляется с помощью свойства XMLHttpRequest.upload.

В запросе не используется объект ReadableStream.

283
29 апр. '15 в 23:53
источник

Связанные вопросы


Похожие вопросы

Прошел эту проблему, ниже мое заключение к этой проблеме и мое решение.

В соответствии со стратегией CORS (настоятельно рекомендуем вам прочитать об этом) Вы не можете просто заставить браузер прекратить отправку запроса OPTIONS, если он сочтет это необходимым.

Есть два способа обойти это:

  1. Убедитесь, что ваш запрос является "простым запросом"
  2. Установите Access-Control-Max-Age для запроса OPTIONS

Простой запрос

Простой межсайтовый запрос - это тот, который удовлетворяет всем следующим условиям:

Единственные допустимые методы:

  • ПОЛУЧИТЬ
  • ГОЛОВА
  • СООБЩЕНИЕ

Помимо заголовков, автоматически устанавливаемых пользовательским агентом (например, Connection, User-Agent и т.д.), Единственными заголовками, которые разрешено устанавливать вручную, являются:

  • принимать
  • Accept-Language
  • Content-Language
  • Тип содержимого

Единственные допустимые значения для заголовка Content-Type:

  • применение/х-WWW-форм-urlencoded
  • многочастному/форм-данных,
  • текст/обычный

Простой запрос не вызовет предполетный запрос ОПЦИИ.

Установить кеш для проверки ОПЦИИ

Вы можете установить Access-Control-Max-Age для запроса OPTIONS, чтобы он не проверял разрешение снова, пока не истечет срок его действия.

Access-Control-Max-Age дает значение в секундах, в течение которого можно кэшировать ответ на запрос предварительной проверки без отправки другого запроса предварительной проверки.

Ограничение отмечено

  • Для Chrome максимальное количество секунд для Access-Control-Max-Age составляет 600 что составляет 10 минут, согласно исходному коду Chrome.
  • Access-Control-Max-Age работает только для одного ресурса каждый раз, например, запросы GET с одинаковым URL-путем, но разные запросы будут обрабатываться как разные ресурсы. Таким образом, запрос ко второму ресурсу будет по-прежнему вызывать предварительный запрос.
159
02 нояб. '16 в 9:48
источник

Пожалуйста, обратитесь к этому ответу о фактической потребности в запросах предоплаченных ВАРИАНТОВ: CORS - Какова мотивация внедрения предполетных запросов?

Чтобы отключить запрос OPTIONS, ниже для выполнения ajax-запроса должны быть выполнены условия:

  • Запрос не устанавливает пользовательские заголовки HTTP, такие как "application/xml" или "application/json" и т.д.
  • Метод запроса должен быть одним из GET, HEAD или POST. Если POST, тип содержимого должен быть одним из application/x-www-form-urlencoded, multipart/form-data или text/plain

Ссылка: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

135
18 мая '15 в 9:08
источник

Когда вы открываете консоль отладки и включен параметр " Disable Cache, запросы предварительной проверки всегда будут отправляться (т.е. Перед каждым запросом). если вы не отключите кеш, запрос перед полетом будет отправлен только один раз (на сервер)

41
24 февр. '16 в 0:28
источник

Да, можно избежать опций запроса. Запрос параметров - это предварительный запрос при отправке (публикации) любых данных в другой домен. Это проблема безопасности браузера. Но мы можем использовать другую технологию: транспортный слой iframe. Я настоятельно рекомендую вам забыть о любой конфигурации CORS и использовать готовое решение, и оно будет работать где угодно.

Посмотрите здесь: https://github.com/jpillora/xdomain

И рабочий пример: http://jpillora.com/xdomain/

38
18 мая '15 в 7:30
источник

Как уже упоминалось в предыдущих сообщениях, запросы OPTIONS существуют по какой-то причине. Если у вас есть проблема с большим временем отклика с вашего сервера (например, заграничное соединение), вы также можете использовать кеш браузера для предполетных запросов.

Отвечайте серверу с заголовком Access-Control-Max-Age, а для запросов, которые отправляются на ту же конечную точку, запрос предварительной проверки будет кэшироваться и больше не встречаться.

14
22 февр. '16 в 6:02
источник

Для разработчика, который понимает причину, по которой он существует, но ему необходимо получить доступ к API, который не обрабатывает вызовы OPTIONS без авторизации, мне нужен временный ответ, чтобы я мог развиваться локально, пока владелец API не добавит надлежащую поддержку SPA CORS или я не получу API прокси-сервера.

Я обнаружил, что вы можете отключить CORS в Safari и Chrome на Mac.

Отключить такую ​​же политику происхождения в Chrome

Chrome: закройте Chrome, откройте терминал и вставьте следующую команду: open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir

Safari: Отключение политики одного и того же происхождения в Safari

Если вы хотите отключить политику одного и того же происхождения в Safari (у меня есть 9.1.1), вам нужно только включить меню разработчика и выбрать "Отключить ограничения перекрестного происхождения" в меню разработки.

12
10 марта '17 в 21:27
источник

Я решил эту проблему как.

if($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && ENV == 'devel') {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: X-Requested-With');
    header("HTTP/1.1 200 OK");
    die();
}

Это только для развития. При этом я жду 9 мс и 500 мс, а не 8 и 500 мс. Я могу это сделать, потому что производственное приложение JS будет находиться на той же машине, что и на производстве, поэтому не будет OPTIONS, но разработка - моя локальная.

6
02 марта '16 в 19:06
источник

Вы не можете, но вы можете избежать использования CORS с помощью JSONP.

5
16 мая '15 в 19:32
источник

Проведя целую полтора дня, пытаясь справиться с подобной проблемой, я обнаружил, что это связано с IIS.

Проект Web API был настроен следующим образом:

// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
    var cors = new EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);
    //...
}

У меня не было определенных параметров конфигурации CORS в узле web.config> system.webServer, как я видел во многих сообщениях

Нет специального кода CORS в global.asax или в контроллере в качестве декоратора

Проблема была в настройках пула приложений.

Режим управляемого конвейера был настроен на классический (сменил его на интегрированный), а Identity была установлена на Network Service (сменила его на ApplicationPoolIdentity)

Изменение этих настроек (и обновление пула приложений) исправило это для меня.

0
24 янв. '18 в 22:08
источник

Я думаю, вы отправляете запрос на перекрестный домен.

Для междоменных запросов установка типа содержимого для чего-либо, кроме приложения /x-www-form-urlencoded, multipart/form-data или text/plain, приведет к тому, что браузер отправит на сервер запрос предварительной проверки OPTIONS.

Поэтому вам может потребоваться указать contentType, чтобы избежать запроса OPTION.

Пример JQuery:

$.ajax({
    url: "http://crossdomainurl",
    type: "POST",
    contentType: 'text/plain'
}); 
-1
18 марта '18 в 20:28
источник

Что сработало для меня, было импортировать "github.com/gorilla/handlers", а затем использовать его следующим образом:

router := mux.NewRouter()
router.HandleFunc("/config", getConfig).Methods("GET")
router.HandleFunc("/config/emcServer", createEmcServers).Methods("POST")

headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOk := handlers.AllowedOrigins([]string{"*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})

log.Fatal(http.ListenAndServe(":" + webServicePort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))

Как только я выполнил запрос POJ Ajax и связал с ним данные JSON, Chrome всегда будет добавлять заголовок Content-Type, который не был в моей предыдущей конфигурации AllowedHeaders.

-1
17 мая '17 в 18:52
источник

Он может быть разрешен в случае использования прокси-сервера, который перехватывает запрос и записывает соответствующие заголовки. В конкретном случае с лаком это были бы правила:

if (req.http.host == "CUSTOM_URL" ) {
set resp.http.Access-Control-Allow-Origin = "*";
if (req.method == "OPTIONS") {
   set resp.http.Access-Control-Max-Age = "1728000";
   set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, PATCH, OPTIONS";
   set resp.http.Access-Control-Allow-Headers = "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since";
   set resp.http.Content-Length = "0";
   set resp.http.Content-Type = "text/plain charset=UTF-8";
   set resp.status = 204;
}

}

-2
31 янв. '18 в 17:23
источник

Одно из решений, которое я использовал в прошлом - скажем, что ваш сайт находится на mydomain.com, и вам нужно сделать запрос ajax для foreigndomain.com

Настройте переписку IIS из своего домена в чужой домен.

<rewrite>
  <rules>
    <rule name="ForeignRewrite" stopProcessing="true">
        <match url="^api/v1/(.*)$" />
        <action type="Rewrite" url="https://foreigndomain.com/{R:1}" />
    </rule>
  </rules>
</rewrite>

на вашем сайте mydomain.com - вы можете сделать один и тот же запрос источника, и нет необходимости в каких-либо запросах опций:)

-2
30 окт. '17 в 4:38
источник

Возможно, есть решение (но я его не тестировал): вы можете использовать CSP (Политика безопасности контента), чтобы включить удаленный домен и браузеры, возможно, пропустит проверку запроса CORS OPTIONS.

Я, если найду какое-то время, буду проверять это и обновлять этот пост!

CSP: https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Content-Security-Policy

Спецификация CSP: https://www.w3.org/TR/CSP/

-3
26 июля '18 в 13:00
источник

Посмотрите другие вопросы по меткам или Задайте вопрос