http options请求
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了http options请求相关的知识,希望对你有一定的参考价值。
参考技术A OPTIONS请求即预检请求,可用于检测服务器允许的http方法。当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起OPTIONS请求,即CORS预检请求,服务器若接受该跨域请求,浏览器才继续发起正式请求。从很多资料我们可以了解到使用OPTIONS方法对服务器发起请求,可以检测服务器支持哪些 HTTP 方法。但是这次我们并没有主动去发起OPTIONS请求,那OPTIONS请
MDN的 CORS 一文中提到:
所以这个跨域请求触发了浏览器自动发起OPTIONS请求,看看此次跨域请求具体触发了哪些条件。
可见一旦达到触发条件,跨域请求便会一直发送2次请求,这样增加的请求数是否可优化呢?答案是可以,OPTIONS预检请求的结果可以被缓存。
Access-Control-Max-Age这个响应首部表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存的最长时间,单位是秒。(MDN)
如果值为 -1,则表示禁用缓存,每一次请求都需要提供预检请求,即用OPTIONS请求进行检测。
参考: https://juejin.cn/post/6844903821634699277
使用 EnableCors 时“请求的资源不支持 http 方法 'OPTIONS'”
【中文标题】使用 EnableCors 时“请求的资源不支持 http 方法 \'OPTIONS\'”【英文标题】:"The requested resource does not support http method 'OPTIONS'" when using EnableCors使用 EnableCors 时“请求的资源不支持 http 方法 'OPTIONS'” 【发布时间】:2018-01-19 05:23:23 【问题描述】:我想在 Asp.net Web Api 中的一项特定操作上启用 CORS。以下是我的尝试:
[Route("api/mycontroller/myaction")]
[HttpPost]
[EnableCors("https://example.com", "*", "post")]
public async Task<IHttpActionResult> MyAction()
...
但是当我向路由发送 OPTIONS 请求时,我收到一个错误:“请求的资源不支持 http 方法 'OPTIONS'。”我也尝试删除 [HttpPost] 注释无济于事。 我错过了什么?
【问题讨论】:
嗯,您是否尝试过仅将请求作为 POST 而不是 OPTIONS 发送?我认为当您发出 CORS 请求时,浏览器会在后台为您执行 OPTIONS 内容(不过我可能弄错了)。 POST 请求本身可以工作,但是浏览器首先发送一个 OPTIONS 请求并且失败了,所以它永远不会发送 POST。 [EnableCors("example.com", "*", "post, options")]?告诉操作接受 OPTIONS 请求以及 POST 相同。如果我将 [HttpOptions] 注释与 [HttpPost] 一起添加,我不会收到错误消息,但它会尝试执行操作方法并需要授权。 EnableCors 应该响应 OPTIONS 请求。 【参考方案1】:对我来说,我通过将以下代码添加到 Global.asax.cs 文件的 Application_BeginRequest 函数中,将以下标头添加到请求中:
protected void Application_BeginRequest()
if (Request.Headers.AllKeys.Contains("Origin", StringComparer.CurrentCultureIgnoreCase)
&& Request.HttpMethod == "OPTIONS")
Response.AddHeader("Access-Control-Allow-Headers", "content-type", "accept", "pragma", "cache-control", "authorization");
Response.End();
我不知道为什么会这样。 出于好奇,我尝试使用星号添加所有标头,但随后 Web API 抱怨缺少授权标头。
【讨论】:
你救了我的命 :) 我还需要将代码添加到 system.weserver 标签内的 web.config 文件中<httpProtocol> <customHeaders> <clear /> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" /> <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> </customHeaders> </httpProtocol>
【参考方案2】:
您可能错过了对HttpConfiguration.EnableCors
的更高级别调用,如下所述:https://enable-cors.org/server_aspnet.html。
将此代码添加到您的配置中:
public static void Register(HttpConfiguration config)
// New code
config.EnableCors();
【讨论】:
我认为在 WebApiConfig.cs 中调用config.EnableCors()
将为整个 API 启用 CORS。我没有意识到这是使用注释的先决条件。我也确实安装了 OWIN CORS,根据***.com/a/29452419/560722 将其删除【参考方案3】:
为确保OPTIONS
请求在到达您的应用代码之前由您的应用代码而不是系统的其他部分处理,您可以尝试将以下内容添加到您的web.config
:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
您可能还需要包括:
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS"
modules="IsapiModule" requireAccess="None"
scriptProcessor="C:\Windows\System32\inetsrv\asp.dll"
resourceType="Unspecified" />
在IIS hijacks CORS Preflight OPTIONS request查看答案。
或者甚至只是这样:
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS"
modules="ProtocolSupportModule" requireAccess="None" />
如果这些都不起作用,那么在您的global.asax
或其他代码中您可以尝试:
if (filterContext.HttpContext.Request.HttpMethod == "OPTIONS")
filterContext.HttpContext.Response.Flush();
…或其他一些变体,例如:
if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OridinalIgnoreCase)
&& Request.HttpMethod == "OPTIONS")
Response.Flush();
不管你用什么具体的代码来做,重点是:
确保OPTIONS
请求实际上已被您的应用代码捕获/处理,而不是在到达您的应用代码之前被系统的其他部分捕获/处理
确保在应用程序代码中明确处理 OPTIONS
请求
在您的应用程序代码中处理OPTIONS
只需执行Response.Flush()
或者我不确定另一种方法是否与您的编码情况相关,但我会提到以防万一:
public HttpResponseMessage Options()
var response = new HttpResponseMessage
StatusCode = HttpStatusCode.OK
;
return response;
【讨论】:
感谢您提供非常全面的答案,我必须维护一个旧网站并且<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" />
有效。以上是关于http options请求的主要内容,如果未能解决你的问题,请参考以下文章