http - metodos - ¿Por qué se envía una solicitud de OPCIONES y puedo desactivarla?
metodos http (14)
Como ya se mencionó en publicaciones anteriores, las solicitudes de
OPTIONS
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 guarde 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 almacenará en caché y ya no se producirá.
Estoy construyendo una API web. Descubrí que cada vez que uso Chrome para PUBLICAR, LLEGAR a mi API, siempre hay una solicitud de OPCIONES enviada antes de la solicitud real, lo cual es bastante molesto. Actualmente obtengo que el servidor ignore cualquier solicitud de OPCIONES. Ahora mi pregunta es ¿qué tiene de bueno enviar una solicitud de OPCIONES para duplicar la carga del servidor? ¿Hay alguna forma de evitar que el navegador envíe solicitudes de OPCIONES por completo?
Consulte esta respuesta sobre la necesidad real de solicitud de OPCIONES pre-voladas: CORS - ¿Cuál es la motivación detrás de la introducción de solicitudes de verificación previa?
Para deshabilitar la solicitud OPTIONS, se deben cumplir las siguientes condiciones para la solicitud ajax:
- La solicitud no establece encabezados HTTP personalizados como ''application / xml'' o ''application / json'', etc.
-
El método de solicitud debe ser GET, HEAD o POST.
Si es POST, el tipo de contenido debe ser uno de
application/x-www-form-urlencoded
,multipart/form-data
otext/plain
Referencia: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
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 deshabilita el caché, se enviará una solicitud previa al vuelo solo una vez (por servidor)
Después de pasar todo un día y medio tratando de resolver 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 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 de CORS en global.asax o en el controlador como decorador
El problema era la configuración del grupo de aplicaciones .
El modo de canalización administrado se configuró en clásico (lo cambió a integrado ) y la Identidad se configuró en Servicio de red (lo cambió a ApplicationPoolIdentity )
Cambiar esa configuración (y actualizar el grupo de aplicaciones) me lo arregló.
He 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 la solicitud de OPCIONES si cree que es necesario.
Hay dos formas de solucionarlo:
- Asegúrese de que su solicitud sea una "solicitud simple"
-
Establezca
Access-Control-Max-Age
para la solicitud OPTIONS
Solicitud simple
Una solicitud simple entre sitios es aquella que cumple con todas las siguientes condiciones:
Los únicos métodos permitidos son:
- OBTENER
- CABEZA
- ENVIAR
Además de los encabezados configurados automáticamente por el agente de usuario (por ejemplo, Connection, User-Agent, etc.), los únicos encabezados que se pueden configurar manualmente son:
- Aceptar
- Aceptar lenguaje
- Lenguaje de contenido
- Tipo de contenido
Los únicos valores permitidos para el encabezado Content-Type son:
- application / x-www-form-urlencoded
- multipart / form-data
- Texto sin formato
Una solicitud simple no causará una solicitud de OPCIONES previas al vuelo.
Establecer un caché para la verificación de OPCIONES
Puede establecer un
Access-Control-Max-Age
para la solicitud OPTIONS, de modo que no vuelva a verificar el permiso hasta que caduque.
Access-Control-Max-Age proporciona el valor en segundos durante cuánto tiempo se puede almacenar en caché la respuesta a la solicitud de verificación previa sin enviar otra solicitud de verificación previa.
Limitación observada
-
Para Chrome, los segundos máximos para
Access-Control-Max-Age
son600
que son 10 minutos, según el código fuente de Chrome -
Access-Control-Max-Age
solo funciona para un recurso cada vez, por ejemplo, las solicitudesGET
con la misma ruta URL pero las consultas diferentes se tratarán como recursos diferentes. Por lo tanto, la solicitud al segundo recurso seguirá activando una solicitud de verificación previa.
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 espero 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.
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 de Ajax y le adjunté datos JSON, Chrome siempre agregaba el encabezado Content-Type que no estaba en mi configuración anterior de AllowHeaders.
No puedes pero puedes evitar CORS usando JSONP.
Para un desarrollador que entiende la razón por la que existe pero necesita acceder a una API que no maneja llamadas de OPTIONS sin autenticación, necesito una respuesta temporal para poder desarrollar localmente hasta que el propietario de la API agregue el soporte adecuado de SPA CORS o obtenga una API proxy está funcionando.
Descubrí que puedes deshabilitar CORS en Safari y Chrome en una Mac.
Deshabilitar la misma política de origen en Chrome
Chrome: Salga de Chrome, abra un 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), solo necesita habilitar el menú de desarrollador y seleccionar "Deshabilitar restricciones de origen cruzado" en el menú de desarrollo.
Sí, es posible evitar la solicitud de opciones. La solicitud de opciones es una solicitud de verificación previa cuando envía (publica) cualquier dato a otro dominio. Es un problema de seguridad del navegador. Pero podemos usar otra tecnología: capa de transporte de iframe. Le recomiendo que se olvide de cualquier configuración de CORS y use una solución preparada y funcionará en cualquier lugar.
Echa un vistazo aquí: https://github.com/jpillora/xdomain
Y ejemplo de trabajo: http://jpillora.com/xdomain/
Se puede resolver en caso de uso de 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;
}
}
Tal vez haya una solución (pero no la probé): 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 solicitud de OPCIONES DE CORS.
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 ajax a foreigndomain.com
Configure una reescritura de IIS de su dominio al dominio externo, p. Ej.
<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 sitio de mydomain.com: puede hacer una misma solicitud de origen y no hay necesidad de ninguna solicitud de opciones :)
editar 2018-09-13 : se agregaron algunas precisiones sobre esta solicitud previa al vuelo y cómo evitarla al final de esta respuesta.
OPTIONS
solicitudes de
OPTIONS
son lo que llamamos solicitudes
pre-flight
en
Cross-origin resource sharing (CORS)
.
Son necesarios cuando realiza solicitudes a través de diferentes orígenes en situaciones específicas.
Algunos navegadores realizan esta solicitud previa al vuelo 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 hacer solicitudes de origen cruzado.
Un buen recurso se puede encontrar aquí http://enable-cors.org/
Una forma de manejarlos 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 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
editar 2018-09-13
La solicitud CORS
OPTIONS
se activa solo en algunos casos, como se explica en los
documentos de MDN
:
Algunas solicitudes no activan una verificación previa CORS. Esas se llaman "solicitudes simples" en este artículo, aunque la especificación Fetch (que define CORS) no usa ese término. Una solicitud que no desencadena una verificación previa de CORS (una llamada "solicitud simple") es una que cumple con las siguientes condiciones:
Los únicos métodos permitidos son:
- OBTENER
- CABEZA
- ENVIAR
Además de los encabezados configurados automáticamente por el agente de usuario (por ejemplo, Connection, User-Agent o cualquiera de los otros encabezados con nombres definidos en la especificación Fetch como "nombre de encabezado prohibido"), los únicos encabezados que pueden configurados manualmente son aquellos que la especificación Fetch define como un "encabezado de solicitud protegido por CORS", que son:
- Aceptar
- Aceptar lenguaje
- Lenguaje de contenido
- Tipo de contenido (pero tenga en cuenta los requisitos adicionales a continuación)
- DPR
- Enlace descendente
- Guardar datos
- Ancho de ventana
- Anchura
Los únicos valores permitidos para el encabezado Content-Type son:
- application / x-www-form-urlencoded
- multipart / form-data
- Texto sin formato
Ningún detector de eventos está registrado en ningún objeto XMLHttpRequestUpload utilizado en la solicitud; se accede a ellos utilizando la propiedad XMLHttpRequest.upload.
No se utiliza ningún objeto ReadableStream en la solicitud.