假设有一简单架构分为先后两部分,其一是Angular构成的前端页面站点,另外一个则是经过ASP.NET Web API搭建的后端服务站点。两个站点由于分别布署,全部会有CORS(Cross-Origin Resource Sharing)的问题。前端
再假设后端已经对此作好相应配置,好比在web.config里加上了:web
<httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD" /> <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" /> </customHeaders> </httpProtocol>
那么当前端调用后端接口:json
save(data: any) : Observable<any> { return this.http.post(`${this.apiUrl}`, data) }
后端对应接口内的逻辑理论上应该是可以被正常执行的:后端
[HttpPost] [Route("api/save")] public HttpResponseMessage Save(SomeModel model) { //内部逻辑 }
但结果是出现了Message:"The requested resource does not support http method 'OPTIONS'."
错误。api
产生此问题的缘由在于HttpClient的post方法默认是采用application/json的内容类型(Content-Type)。bash
而CORS规范中有两种类型:服务器
前者无需额外的处理,但对于内容类型的支持,仅限三种:架构
对于除此之外的内容类型,好比application/json,CORS会以预检请求方式(Preflighted requests)处理。app
Preflighted requests要求必须首先使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否容许该实际请求。post
而在上面的后端服务代码中并无准备相应的处理OPTIONS请求的接口,因此才会有这样的错误。
对应修正方法很简单,在同一接口方法上加上处理OPTIONS请求的逻辑:
[HttpOptions, HttpPost] [Route("api/save")] public HttpResponseMessage Save(SomeModel model) { if (Request.Method == HttpMethod.Options) return new HttpResponseMessage(HttpStatusCode.OK); //内部逻辑 }
有关CORS的详细描述,建议参考官方文档——Cross-Origin Resource Sharing (CORS)