欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Web API对application/json内容类型的CORS支持

程序员文章站 2022-08-25 20:53:19
假设有一简单架构分为前后两部分,其一是Angular构成的前端页面站点,另一个则是通过ASP.NET Web API搭建的后端服务站点。两个站点因为分别布署,所有会有CORS(Cross Origin Resource Sharing)的问题。 再假设后端已经对此做好相应配置,比如在web.conf ......

假设有一简单架构分为前后两部分,其一是Angular构成的前端页面站点,另一个则是通过ASP.NET Web API搭建的后端服务站点。两个站点因为分别布署,所有会有CORS(Cross-Origin Resource Sharing)的问题。

再假设后端已经对此做好相应配置,比如在web.config里加上了:

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

那么当前端调用后端接口:

  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'."错误。

产生此问题的原因在于HttpClient的post方法默认是采用application/json的内容类型(Content-Type)。

而CORS规范中有两种类型:

  • Simple requests
  • Preflighted requests

前者无需额外的处理,但对于内容类型的支持,仅限三种:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

对于除此以外的内容类型,比如application/json,CORS会以预检请求方式(Preflighted requests)处理。

Preflighted requests要求必须首先使用OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。

而在上面的后端服务代码中并没有准备相应的处理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)