【问题标题】:Access-Control-Expose-Headers setting ignoredAccess-Control-Expose-Headers 设置被忽略
【发布时间】:2017-03-04 19:51:57
【问题描述】:

在我的 Apache Web 服务器配置中,我添加了对不属于标准六的两个标头的支持:

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Expose-Headers: Content-Disposition,X-Filename

我的文件导出 CGI 脚本打印包含这两个字段数据的标题,例如:

...
print "Content-Disposition: attachment; filename=%s\n" % (out_fn)
print "X-Filename: %s\n" % (out_fn)
...

我的客户端 AJAX 调用尝试在 AJAX 请求成功时检索 Content-Disposition 的值:

var export_form = new FormData();
export_form.append("settings", JSON.stringify(settings));
export_form.append("format", format);
$.ajax({
    url: "services/export_data.py",
    type: "POST",
    async: true,
    cache: false,
    data: export_form,
    processData: false,
    contentType: false,
    success: function(response, textStatus, jqXHR) {
        console.log("success");
        console.log(jqXHR.getAllResponseHeaders());
        console.log(jqXHR.getResponseHeader('Content-Disposition'));
    },
    error: function(jqXHR, textStatus, errorThrown) {
        console.log("export_form submit failed:", jqXHR.status, jqXHR.statusText);
        console.log(jqXHR);
    }
});

我在客户端的测试请求完成并运行success 回调,我在response 字段中取回文件数据,但我得到null 的响应标头Content-Disposition

换句话说,console.log(jqXHR.getAllResponseHeaders()) 的样本结果是:

Date: Sat, 04 Mar 2017 19:42:27 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips mod_python/3.5.0- Python/2.7.5 mod_perl/2.0.10 Perl/v5.16.3
Transfer-Encoding: chunked
Content-Type: application/pdf
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Disposition,X-Filename
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100

console.log(jqXHR.getResponseHeader('Content-Disposition'))的结果为空:

null

为什么我的 AJAX 请求无法检索到 Content-Disposition 的值,当我通过 Web 服务器配置明确提供它并且在响应中正确设置它时?


为了解决换行问题,我使用sys.stdout.write 来获得对输出的更多控制,例如:

sys.stdout.write("Content-Type: %s\n" % (mime_type))
sys.stdout.write("Content-Disposition: attachment; filename=%s\n" % (output_fn))
sys.stdout.write("X-Filename: %s\n" % (output_fn))
sys.stdout.write("Content-Description: File to download\n\n")
with open(out_fn, "rb") as out_fh:
    sys.stdout.write(out_fh.read())

不幸的是,通过console.log(jqXHR.getResponseHeader('Content-Disposition'))console.log(jqXHR.getResponseHeader('X-Filename'))(它们都是null)的AJAX 响应仍然看不到这两个标头。

【问题讨论】:

  • 响应中是否包含实际的标头(您可以在浏览器的开发者控制台中看到它们)吗?
  • @AlexReynolds 当您使用 python print 时,您不必添加新的换行符,因为 print 实际上添加了它。您确定mod_headers Apache 模块已启用吗?当我从另一个域进行 AJAX 调用并返回标头时,它在我身上完美地工作,无需换行符字符串终止。请在此处查看屏幕截图:zikro.gr/dbg/srv/apache-custom-cors-headers-1.png。我不能给你一个链接,因为我在虚拟机上运行 Apache 服务器,但是如果你想看的话,我可以提供它。
  • 我已经打开了运行 Apache 2.4 的虚拟机,并提供了一个工作示例。您可以在此处zikro.gr/dbg/srv/apache-headers 尝试使用 AJAX 调用的工作脚本,如果您检查源代码,您将看到 url 在不同的服务器上。 printsys.stdout.write 都在工作并在控制台窗口中输出标题。请在此处查看控制台屏幕截图zikro.gr/dbg/srv/apache-custom-cors-headers-2.png。您是否检查了日志文件是否存在潜在错误? AJAX 调用是否返回 200 Success
  • 你在写Unfortunately, these two headers were still not visible to the AJAX response。它们实际上是否在响应中并且对 Javascript 代码根本不可见,或者它们根本不包含在响应中?您能否发布带有标头的原始响应以及可能包含的数据的前几个字节?您可以使用浏览器的开发者控制台或 curl 等工具来完成。
  • @AlexReynolds 你能提供整个 python cgi 脚本吗?请记住,如果您在标头之前写入任何其他内容,HTTP 响应将不会捕获您的标头。如果在脚本编写标题之前没有输出,那么使用 sys.stdout.write 的示例应该可以工作。 (另外我假设您在使用sys.stdout 之前使用import sys 导入sys 库)。

标签: jquery ajax apache http-headers


【解决方案1】:

Access-Control-Expose-Headers 仅适用于 CORS 请求:在您的情况下,Content-DispositionX-Filename 被添加到允许另一个域查看它是否从您的服务器请求数据的六个标准标头中。

但是,您发送的请求看起来不像是跨域的:URL services/export_data.py 没有指向另一个域,console.log(jqXHR.getAllResponseHeaders()) 的输出包括像 ServerDate 这样的标头不在六个标准和两个公开的标头中。


我认为您的问题是服务器端的,而不是 Javascript,而且您实际上并没有发送要包含的两个标头。

CGI 脚本似乎是用 Python 编写的(基于 URL 中的文件扩展名)。如果是这种情况,print "\n" 实际上会打印两个换行符,并且由于空行分隔 HTTP 中的标头和数据,因此您添加的两个标头将包含在 HTTP 响应中,但被视为数据而不是标头。在添加Content-Disposition 之前是否有任何print 声明?这可以解释为什么它也没有显示为标题。

要解决此问题,只需删除脚本中的尾随 \n

...
print "Content-Disposition: attachment; filename=%s" % (out_fn)
print "X-Filename: %s" % (out_fn)
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-20
    • 2016-05-18
    • 2016-05-18
    • 1970-01-01
    • 2013-06-12
    • 2015-09-12
    • 2019-02-19
    相关资源
    最近更新 更多