无法从前端 JavaScript 访问跨域响应标头

Posted

技术标签:

【中文标题】无法从前端 JavaScript 访问跨域响应标头【英文标题】:Can’t access cross-origin response header from frontend JavaScript 【发布时间】:2017-08-27 19:02:09 【问题描述】:

我正在使用 ReactJScreate-react-app 构建一个简单的网络应用程序。

我在 Heroku 上设置了一个后端 API,我可以在其中发出 POST 请求。一切正常,除了:

当我使用 fetch API 发出 POST 请求时,响应是 100% 正确的,但它只给了我 2 个标准标头。我想获得我的自定义标题。我在回复中添加了公开标题,这是情节转折:当我从 Chrome 检查工具或 Postman(API 工具)查看标题时,它会显示所有标题,包括我的自定义标题。这是我正在使用的获取代码 -

fetch(theUrl, 
  method: 'POST',
  body: JSON.stringify(
    "placeholder": "placeholder"
  )
)
.then(function(res) 
  console.log(res.headers.get('CUSTOM_HEADER_NAME'));
)

如果有什么不同,这个 fetch 方法是从 ReactJS 组件主体之外的函数调用的。

自定义标头的名称是Image-Identification-Path,而我的响应标头中的标头是Access-Control-Expose-Headers for Image-Identification-Path.

总结:如何使用 fetch 获取自定义标头?

【问题讨论】:

这是跨域请求吗?当您说“我在响应中添加了公开标头”时,您的意思是您已将自定义标头的名称添加到 Access-Control-Expose-Headers 响应标头的值中? 是的,这是一个跨域请求。我现在正在本地主机上运行我的应用程序。我也通过在 Heroku 上上传我的应用程序对此进行了测试,但它给出了相同的结果。同样是的,我已将自定义标头的名称添加到 Access-Control-Expose-Headers 响应标头的值中。 您的屏幕截图显示您在 Access-Control-Allow-Headers 标头的值中有 Image-Identification-Path 标头名称。您需要在 Access-Control-Expose-Headers 标头的值中设置它。 (Access-Control-Allow-Headers 用于列出自定义 request 标头名称。) 【参考方案1】:

您必须配置将请求发送到的服务器,使其响应具有Access-Control-Expose-Headers 标头,该标头具有您的自定义响应标头的名称。

否则,如果您的浏览器在该 Access-Control-Expose-Headers 标头中看不到您的自定义标头的名称,它将不允许您访问自定义标头的值。

在这种情况下,如果您在 Postman 甚至浏览器开发工具中查看响应,预计您仍然可以看到自定义标头。

但仅仅因为浏览器在响应中获取自定义标头并不意味着浏览器会将其公开给您的前端 javascript 代码。

对于跨域请求,如果该标头名称在 Access-Control-Expose-Headers 值中,浏览器只会将该自定义响应标头公开给您的前端代码。

【讨论】:

感谢您的回答,但正如我在问题中所说,我已经在我的服务器响应标头中包含了 Access-Control-Expose-Headers 标头。 那么您的自定义响应标头的名称是什么? Access-Control-Expose-Headers 的价值是什么?请使用***.com/posts/43175710/edit 更新/编辑您的问题以包含该信息。否则这里的任何人都很难想象问题的原因可能是什么 对于任何面临同样问题的人,这个答案是对的,只是我添加了 Access-Control-Allow-Headers 而不是 Access-Control-Expose-Headers 只是询问知识 - 即使不公开,Google Chrome 或 Postman 怎么能看到所有标题?它们不也只是一个客户端应用吗? 浏览器对 Web 应用程序执行同源策略,这些应用程序的范围仅限于特定来源。 Postman 的范围不限于任何特定的来源——而是用户安装的扩展程序/附加组件;它不是一个不受信任的网络应用程序。因此,所有其他客户端应用程序——Postman 和除浏览器之外的所有其他应用程序——甚至都没有“起源”的概念。这个“起源”概念是一个网络应用程序的东西,这与网络应用程序托管在特定网站上的事实有关。与网络应用不同,Postman 不托管在任何特定的网站/来源。【参考方案2】:

我知道这个问题很老,但我昨天遇到了这个问题,给定的答案对我不起作用。

article 中给出了我找到的解决方案。基本上:

您不能直接访问对 fetch 调用的响应中的标头 - 您必须在对标头使用 entry() 方法后进行迭代。

因此,在您的特定情况下,您应该能够通过使用以下代码来实现目标:

fetch(theUrl, 
  method: 'POST',
  body: JSON.stringify(
    "placeholder": "placeholder"
  )
)
.then(response =>  
  for (var pair of response.headers.entries())  // accessing the entries
     if (pair[0] === 'CUSTOM_HEADER_NAME')  // key you're looking for, in your case Image-Identification-Path
        let imagePath = pair[1]; //// saving that value
     
  
  .... )

【讨论】:

以上是关于无法从前端 JavaScript 访问跨域响应标头的主要内容,如果未能解决你的问题,请参考以下文章

Javascript fetch api:无法检索某些响应标头

跨域资源共享错误:预检响应不允许标头

如何从跨域 Ajax 请求访问 Content-Length 标头?

验证来自 Javascript 的跨域请求

Access-Control-Expose-Headers 响应报头跨域 公开响应头

跨域请求过滤掉了我的大部分 API 响应标头