为啥我的“multipart/form-data”标头不能阻止发送预检 (OPTIONS) 请求?

Posted

技术标签:

【中文标题】为啥我的“multipart/form-data”标头不能阻止发送预检 (OPTIONS) 请求?【英文标题】:Why isn't my "multipart/form-data" header preventing preflight (OPTIONS) requests from being sent?为什么我的“multipart/form-data”标头不能阻止发送预检 (OPTIONS) 请求? 【发布时间】:2021-02-25 15:15:04 【问题描述】:

我正在使用 Angular 9。我有这些请求来获取二进制图像数据...

headersMultiPartForm = new HttpHeaders().set('Content-Type', 'multipart/form-data');
    ...
  getImage(id) 
    let api = `$this.endpoint/person-library-image?id=$id`;
    return this.http
      .get(api, headers: this.headersMultiPartForm, responseType: "blob")
      .pipe(retry(this.retry), catchError(this.handleError));
  

    ...
results.forEach(( componentarray, key ) => 
    ...
    this.myService.getImage(id).subscribe(data => 
      ...
      this.createImageFromBlob(data, index);
      ...
    , () => 
      ...
    );

);

我注意到请求需要一段时间才能完成,这似乎是因为它们被阻止等待 OPTIONS 请求完成。我想阻止发送这些预检 OPTIONS 请求。我认为我的“multipart/form-data”会阻止预检请求,但显然不是......

当我通过右键单击并复制为 CURL 检查实际请求时,我看到...

curl 'http://localhost:7071/api/person-library-image?id=127' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:81.0) Gecko/20100101 Firefox/81.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: http://localhost:4200/picture-library' -H 'Content-Type: multipart/form-data' -H 'Authorization: JWT <token>' -H 'Origin: http://localhost:4200' -H 'Connection: keep-alive' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache'

我有一个拦截器添加了 Authorization 标头,但我不知道其他标头来自哪里。有什么想法可以关闭它们以防止这些预检 OPTIONS 请求吗?

【问题讨论】:

这能回答你的问题吗? Why is an OPTIONS request sent and can I disable it? 我尝试按照建议添加额外的“Access-Control-Max-Age: 600”标头,但继续发送 OPTIONS 请求。 Content-Type: multipart/form-data 应该是simple request,不需要预检;您的请求是否还有其他内容(例如由拦截器添加)将其排除在该类别之外? 【参考方案1】:

你说的是Simple vs Non-simple CORS requests。

确实,带有application/x-www-form-urlencoded Content-Type 的 POST 很简单,如帖子中所述,因此不需要预检。但是,有一个重要的注意事项就是您的情况:

☝ Another tricky important condition - to be simple requests must have no manually 
set headers. Default headers sent by browser are OK, we are talking only about 
headers set by you from your request maker like XHR/fetch/axios/superagent/jQuery Ajax. 
BTW request maker can set it without your agreement, so better start with pure 
browser-native XHR of fetch API, don't use superagent/axios unless you know why
you need it. If you need to set a header by yourself still  and still want keep 
request simple you are allowed to white-listed request headers and their values, they
called CORS-safelisted. You can find their list and allowed values on fetch spec: 
https://fetch.spec.whatwg.org/#cors-safelisted-request-header

检查请求中的标头,可能您有一些添加它的拦截器,根据https://fetch.spec.whatwg.org/#cors-safelisted-request-header

,它们很可能不是CORS-safelisted

【讨论】:

以上是关于为啥我的“multipart/form-data”标头不能阻止发送预检 (OPTIONS) 请求?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用 multipart/form-data 时不能正确发送带有 Unicode 的 POST 名称?

为啥在使用 multipart/form-data 时不能正确发送带有 Unicode 的 POST 名称?

为啥上传文件要使用multipart/form-data

html中表单使用post方式提交,为啥没有值

为啥不总是预检 POST 请求?

curl 更改 multipart/form-data 路径参数