¿Por qué se envía una solicitud de OPCIONES y puedo desactivarla?


Estoy construyendo una api web. Encontré cada vez que uso Chrome para PUBLICAR, LLEGAR a mi API, siempre hay una solicitud de OPCIÓN enviada antes de la solicitud real, que es bastante molesto. Actualmente consigo que el servidor ignore cualquier solicitud de OPCIONES. Ahora mis preguntas es ¿qué es bueno enviar una solicitud de OPCIÓN para duplicar la carga del servidor? ¿Hay alguna forma de detener por completo el envío de solicitudes de OPCIONES por parte del navegador?

 229
Author: mplungjan, 2015-04-29

15 answers

Editar 2018-09-13 : se agregaron algunas precisiones sobre esta solicitud previa al vuelo y cómo evitarla al final de esta respuesta.

OPTIONS las solicitudes son lo que llamamos pre-flight solicitudes en Cross-origin resource sharing (CORS).

Son necesarios cuando estás haciendo solicitudes a través de diferentes orígenes en situaciones específicas.

Esta solicitud previa al vuelo es realizada por algunos navegadores como una medida de seguridad para garantizar que el servidor confíe en la solicitud que se realiza. Significa que el servidor entiende que el el método, el origen y los encabezados que se envían en la solicitud son seguros para actuar.

Su servidor no debe ignorar sino manejar estas solicitudes cada vez que intente realizar solicitudes de origen cruzado.

Un buen recurso se puede encontrar aquí http://enable-cors.org /

Una forma de manejar estos para sentirse cómodo es asegurarse de que para cualquier ruta con el método OPTIONS el servidor envíe una respuesta con este encabezado

Access-Control-Allow-Origin: *

Esto le dirá al navegador que el el servidor está dispuesto a responder solicitudes de cualquier origen.

Para obtener más información sobre cómo agregar soporte CORS a su servidor, consulte el siguiente diagrama de flujo

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

Diagrama de Flujo CORS


Editar 2018-09-13

CORS OPTIONS la solicitud se activa solo en algunos casos, como se explica en MDN docs :

Some requests don’t trigger a CORS preflight. Those are called “simple requests” in this article, though the Fetch spec (which defines CORS) doesn’t use that term. A request that doesn’t trigger a CORS preflight—a so-called “simple request”—is one that meets all the following conditions:

The only allowed methods are:
- GET
- HEAD
- POST

Apart from the headers set automatically by the user agent (for example, Connection, User-Agent, or any of the other headers with names defined in the Fetch spec as a “forbidden header name”), the only headers which are allowed to be manually set are those which the Fetch spec defines as being a “CORS-safelisted request-header”, which are:
- Accept
- Accept-Language
- Content-Language
- Content-Type (but note the additional requirements below)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width

The only allowed values for the Content-Type header are:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain

No event listeners are registered on any XMLHttpRequestUpload object used in the request; these are accessed using the XMLHttpRequest.upload property.

No ReadableStream object is used in the request.
 211
Author: Leo Correa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-13 15:25:43

Por favor refiérase a esta respuesta sobre la necesidad real de una solicitud de OPCIONES pre-flighted: CORS - ¿Cuál es la motivación detrás de la introducción de solicitudes de preflight?

Para deshabilitar la solicitud de OPCIONES, se deben cumplir las siguientes condiciones para la solicitud ajax:

  1. La solicitud no establece encabezados HTTP personalizados como 'application/xml' o 'application/json', etc
  2. El método request tiene que ser uno de GET, HEAD o POST. Si POST, el tipo de contenido debe ser uno de application/x-www-form-urlencoded, multipart/form-data, o text/plain

Referencia: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

 121
Author: device_exec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:47

Han pasado por este problema, a continuación está mi conclusión a este problema y mi solución.

De acuerdo con la estrategia CORS (le recomiendo que lea al respecto) No puede forzar al navegador a dejar de enviar solicitudes de OPCIONES si cree que es necesario.

Hay dos maneras en que puedes evitarlo

    1. Asegúrese de que su solicitud es una "solicitud simple"
    1. Establece Access-Control-Max-Age para la OPCIÓN solicitud

Solicitud simple

Una solicitud simple entre sitios es aquella que cumple todas las siguientes condiciones:

Los únicos métodos permitidos son: - CONSEGUIR - CABEZA - POST

Aparte de los encabezados establecidos automáticamente por el agente de usuario (por ejemplo, Conexión, Agente de usuario, etc.), los únicos encabezados que se permiten configurar manualmente son: - Aceptar - Aceptar-Idioma - Contenido-Idioma - Content-Type

Los únicos valores permitidos para el encabezado Content-Type ser: - application / x-www-form-urlencoded - multipart/form-data - text/plain

Una solicitud simple no causará una solicitud de OPCIÓN de pre-vuelo.

Establecer una caché para la OPCIÓN check

Puede establecer un Access-Control-Max-Age para la solicitud de OPCIÓN, de modo que no vuelva a comprobar el permiso hasta que haya expirado.

Access-Control-Max-Age proporciona el valor en segundos durante cuánto tiempo se puede almacenar en caché la respuesta a la solicitud de comprobación previa sin enviar otra comprobación previa solicitud.

 104
Author: Neekey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-02 06:48:33

Sí es posible evitar la solicitud de opciones. La solicitud de opciones es una solicitud de comprobación previa cuando envía (publica) cualquier dato a otro dominio. Es un problema de seguridad del navegador. Pero podemos usar otra tecnología: iframe transport layer. Le recomiendo encarecidamente que se olvide de cualquier configuración de CORS y utilice la solución readymade y funcionará en cualquier lugar.

Echa un vistazo aquí: https://github.com/jpillora/xdomain

Y trabajando ejemplo: http://jpillora.com/xdomain /

Que tenga un buen día!

 39
Author: user889349,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-18 04:30:34

Cuando tenga la consola de depuración abierta y la opción Disable Cache activada, siempre se enviarán solicitudes de comprobación previa (es decir, antes de cada solicitud). si no deshabilita la caché, se enviará una solicitud previa al vuelo solo una vez (por servidor)

 35
Author: Nir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-03 09:48:29

Como ya se mencionó en publicaciones anteriores, OPTIONS las solicitudes están ahí por una razón. Si tiene un problema con grandes tiempos de respuesta de su servidor (por ejemplo, conexión en el extranjero), también puede hacer que su navegador almacene en caché las solicitudes de comprobación previa.

Haga que su servidor responda con el encabezado Access-Control-Max-Age y para las solicitudes que van al mismo extremo, la solicitud de comprobación previa se habrá almacenado en caché y ya no se producirá.

 14
Author: enpenax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-22 03:02:35

Para un desarrollador que entiende la razón por la que existe, pero necesita acceder a una API que no maneja llamadas de OPCIONES sin autorización, necesito una respuesta temporal para poder desarrollar localmente hasta que el propietario de la API agregue el soporte adecuado de SPA CORS o tenga una API proxy en funcionamiento.

Encontré que puedes desactivar CORS en Safari y Chrome en una Mac.

Deshabilitar la política de mismo origen en Chrome

Chrome: Salir de Chrome, abrir un terminal y pegar este comando: open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir

Safari: Deshabilitar la política del mismo origen en Safari

Si desea deshabilitar la política del mismo origen en Safari (tengo la versión 9.1.1), solo necesita habilitar el menú desarrollador y seleccionar "Deshabilitar restricciones de origen cruzado" en el menú desarrollo.

 12
Author: Joseph Juhnke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:29

He resuelto este problema como.

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();
}

Es solo para el desarrollo. Con esto estoy esperando 9ms y 500ms y no 8s y 500ms. Puedo hacer eso porque la aplicación JS de producción estará en la misma máquina que la producción, por lo que no habrá OPTIONS pero el desarrollo es mi local.

 6
Author: AntiCZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-10 19:47:05

No puede, pero podría evitar CORS usando JSONP.

 5
Author: Jose Mato,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-16 16:32:12

Después de pasar un día y medio tratando de resolver un problema similar, descubrí que tenía que ver con IIS.

Mi proyecto Web API se configuró de la siguiente manera:

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

No tenía opciones de configuración específicas de CORS en la web.config > sistema.Nodo de servidor web como he visto en tantos mensajes

No hay código CORS específico en el global.asax o en el controlador como decorador

El problema fue la configuración del grupo de aplicaciones .

El modo de canalización administrada se estableció en clásico ( lo cambió a integrado ) y la identidad se estableció en Servicio de red (lo cambió a ApplicationPoolIdentity)

Cambiar esa configuración (y actualizar el grupo de aplicaciones) lo arregló para mí.

 0
Author: Ju66ernaut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-04 12:29:23

Lo que funcionó para mí fue importar "github.com/gorilla/handlers" y luego usarlo de esta manera:

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

Tan pronto como ejecuté una solicitud POST Ajax y adjuntando datos JSON a ella, Chrome siempre añadiría el encabezado Content-Type que no estaba en mi configuración anterior AllowedHeaders.

 -1
Author: Kurt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-17 15:52:20

Creo que está enviando una solicitud a cross domain.

Para las solicitudes cross-domain, establecer el tipo de contenido en cualquier otro que application/x-www-form-urlencoded, multipart/form-data, o text / plain activará el navegador para enviar un preflight OPTIONS solicitud al servidor.

Por lo que es posible que deba especificar ContentType para evitar la solicitud de OPCIONES.

Jquery Ejemplo: -

$.ajax({
    url: "http://crossdomainurl",
    type: "POST",
    contentType: 'text/plain'
}); 
 -1
Author: Bala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-04 12:29:33

Tal vez haya una solución (pero no la probé) : podría usar CSP (Content Security Policy) para habilitar su dominio remoto y los navegadores tal vez omitan la verificación de solicitud de OPCIONES CORS.

Si encuentro algo de tiempo, lo probaré y actualizaré este post !

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

Especificación CSP: https://www.w3.org/TR/CSP /

 -1
Author: Arnaud Tournier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-26 10:00:07

Una solución que he utilizado en el pasado - digamos que su sitio está en mydomain.com, y usted necesita hacer una solicitud ajax para foreigndomain.com

Configure una reescritura de IIS desde su dominio al dominio extranjero, por ejemplo,

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

En su mydomain.com sitio-a continuación, puede hacer una misma solicitud de origen, y no hay necesidad de ninguna solicitud de opciones:)

 -2
Author: David McEleney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-30 01:38:15

Se puede resolver en caso de uso de un proxy que intercepte la solicitud y escriba las cabeceras apropiadas. En el caso particular del barniz estas serían las reglas:

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
Author: Rafa Cuestas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-31 14:23:19