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

Estoy construyendo una API web. Encontré que cada vez que uso Chrome para POST, GET para mi API, siempre hay una solicitud de OPCIÓN enviada antes de la solicitud real, lo cual es bastante molesto. Actualmente obtengo el servidor para ignorar 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 manera de detener por completo el navegador de enviar solicitudes de OPCIONES?

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

Son necesarios cuando realiza solicitudes en diferentes orígenes en situaciones específicas.

Esta solicitud previa al vuelo la realizan algunos navegadores como medida de seguridad para garantizar que el servidor confíe en la solicitud que se realiza. Lo que significa que el servidor entiende que 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 cruzadas.

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

Una forma de manejar estos para sentirse cómodos 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 indicará al navegador que 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 diagtwig de flujo

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

Diagrama de flujo CORS

Por favor refiera esta respuesta a la necesidad real de la solicitud de OPCIONES preconfiguradas: CORS: ¿Cuál es la motivación detrás de la introducción de las solicitudes de verificación previa?

Para deshabilitar la solicitud de OPCIONES, a continuación se deben cumplir las condiciones para la solicitud de ajax:

  1. La solicitud no establece encabezados HTTP personalizados como ‘application / xml’ o ‘application / json’, etc.
  2. El método de solicitud debe 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

He pasado por este tema, a continuación se muestra mi conclusión sobre este tema y mi solución.

De acuerdo con la estrategia CORS (recomiendo encarecidamente que leas al respecto). No puedes obligar al navegador a dejar de enviar la solicitud de OPCIÓN si cree que es necesario.

Hay dos formas de solucionarlo

    1. Asegúrese de que su solicitud sea una “simple solicitud”
    1. Establecer Access-Control-Max-Age para la solicitud OPTION

Solicitud simple

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

Los únicos métodos permitidos son: – GET – HEAD – POST

Además de los encabezados configurados automáticamente por el agente de usuario (por ejemplo, conexión, agente de usuario, etc.), los únicos encabezados que pueden establecerse manualmente son: – Aceptar – Aceptar Idioma – Contenido – Idioma – Tipo de contenido

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

Una simple solicitud no causará una solicitud de OPCIÓN previa al vuelo.

Establecer un caché para el control OPTION

Puede establecer un Access-Control-Max-Age para la solicitud OPTION, para que no vuelva a verificar el permiso hasta que caduque.

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

Sí, es posible evitar la solicitud de opciones. La solicitud de opciones es una solicitud de verificación previa cuando envía (publica) cualquier información a otro dominio. Es un problema de seguridad del navegador. Pero podemos usar otra tecnología: capa de transporte iframe. Recomiendo encarecidamente que te olvides de cualquier configuración de CORS y utilices una solución preparada y funcionará en cualquier lugar.

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

Y ejemplo de trabajo: http://jpillora.com/xdomain/

¡Que tengas un buen día!

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

Como ya se mencionó en publicaciones anteriores, las solicitudes OPTIONS están ahí por algún motivo. Si tiene un problema con los tiempos de respuesta grandes de su servidor (por ejemplo, la conexión en el extranjero), también puede tener su navegador en caché las solicitudes de verificación previa.

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

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

Descubrí que puedes desactivar CORS en Safari y Chrome en una Mac.

Deshabilitar la misma política de origen en Chrome

Chrome: salga de Chrome, abra una terminal y pegue 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 9.1.1), entonces solo necesita habilitar el menú del desarrollador, y seleccione “Desactivar restricciones de origen cruzado” en el menú de desarrollo.

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

No puedes, pero puedes evitar CORS usando JSONP.

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

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

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

No tenía las opciones de configuración específicas de CORS en el nodo web.config> system.webServer como he visto en tantas publicaciones

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

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

El modo de canalización administrado se estableció en clásico (se lo cambió a integrado ) y la identidad se configuró en Servicio de red (se cambió a Identidad de conjunto de aplicaciones )

Cambiar esa configuración (y actualizar el grupo de aplicaciones) lo solucionó.

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 AJAx POST y adjuntando datos JSON, Chrome siempre agregaba el encabezado Content-Type que no estaba en mi configuración anterior de AllowedHeaders.

Creo que estás enviando una solicitud para cruzar el dominio .

Para solicitudes de dominio cruzado , establecer el tipo de contenido en cualquier otra cosa que no sea application / x-www-form-urlencoded , multipart / form-data , o text / plain activará el navegador para enviar una solicitud de OPCIONES de verificación previa al servidor.

Por lo tanto, es posible que deba especificar contentType para evitar la solicitud OPTION.

Ejemplo de Jquery:

 $.ajax({ url: "http://crossdomainurl", type: "POST", contentType: 'text/plain' }); 

Quizás haya una solución (pero no la he probado): podría usar CSP (Política de seguridad de contenido) para habilitar su dominio remoto y los navegadores tal vez omitan la verificación de la solicitud CORS OPTIONS.

¡Si encuentro algo de tiempo, lo probaré y actualizaré esta publicación!

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

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

Una solución que he usado en el pasado: digamos que su sitio está en mydomain.com, y necesita hacer una solicitud de Ajax a foreigndomain.com

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

         

en su sitio de midominio.com, puede hacer una solicitud de origen igual y no hay necesidad de ninguna solicitud de opciones 🙂

Se puede resolver en caso de usar un proxy que intercepte la solicitud y escriba los encabezados apropiados. En el caso particular de Varnish 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; } 

}