jQuery和AJAX响应头

183

我有一个jQuery AJAX 调用,服务器返回的响应是一个302重定向。我想把这个重定向加载在一个iframe中,但是当我尝试使用javascript alert查看头信息时,它返回null,即使firebug正确地显示了它。

如果需要的话,这是代码:

$j.ajax({
    type: 'POST',
    url:'url.do',
    data: formData,
    complete: function(resp){
        alert(resp.getAllResponseHeaders());
    }
});

我实际上无法访问服务器端的内容,从而将URL移动到响应主体中,我知道这将是最简单的解决方案,因此对于头文件的解析提供任何帮助都将非常棒。


4
如果您是在2017年或之后访问此问题,请不要浪费时间查看大部分现有的答案。如果您遇到的问题与原帖相同,您有两个选择:1)设置代理服务器来“post”原始服务器并提取目标数据,前端JS将请求代理服务器获取目标数据。或者2)更改服务器代码以允许CORS。 - kmonsoor
8个回答

212

cballou的解决方案适用于您使用旧版本的jQuery。在较新版本中,您也可以尝试:

  $.ajax({
   type: 'POST',
   url:'url.do',
   data: formData,
   success: function(data, textStatus, request){
        alert(request.getResponseHeader('some_header'));
   },
   error: function (request, textStatus, errorThrown) {
        alert(request.getResponseHeader('some_header'));
   }
  });

根据文档,XMLHttpRequest对象从jQuery 1.4开始可用。


5
自 jQuery 版本 >= 1.5 起,应该称之为 jqXHR,它是 XMLHttpRequest 对象的超集。 - Johan

145

如果这是一个CORS请求,您可以在调试工具(如Chrome->检查元素->网络)中看到所有标头,但是xHR对象仅在以下情况下检索标头(通过xhr.getResponseHeader('Header')),即该标头为简单响应标头

  • Content-Type
  • Last-modified
  • Content-Language
  • Cache-Control
  • Expires
  • Pragma

如果不属于这个集合,则必须存在于服务器返回的Access-Control-Expose-Headers标头中。

关于本案,如果这是一个CORS请求,则只有在以下标头也存在的情况下,才能通过XMLHttpRequest对象检索Location标头:

Access-Control-Expose-Headers: Location
如果不是CORS请求,XMLHttpRequest 将毫无问题地检索它。

3
@acdcjunior谢谢你的帮助,我在花费一些时间找出为什么头部响应没有输出后,也有所收获。 - daniyel

39
 var geturl;
  geturl = $.ajax({
    type: "GET",
    url: 'http://....',
    success: function () {
      alert("done!"+ geturl.getAllResponseHeaders());
    }
  });

1
不起作用。也许我正在向另一个站点发出请求?(使用ajax的跨站请求) - Siwei
9
对于像我一样无法使其工作的人,可能是因为你正在进行跨域访问,而jQuery不使用XHR。参考http://api.jquery.com/jQuery.get/。 - h--n
运行得非常好,加一。 - ErShakirAnsari

18
关于 AJAX 和 302 重定向的不幸之处在于,你无法从返回中获取头部信息,因为浏览器从未将它们传递给 XHR。当浏览器看到 302 时,它会自动应用重定向。在这种情况下,你可以在 firebug 中看到 header,因为浏览器已经获取了它,但你在 ajax 中是看不到它的,因为浏览器没有传递它。这就是为什么成功和错误处理程序永远不会被调用。只有完成处理程序被调用。

http://www.checkupdown.com/status/E302.html

The 302 response from the Web server should always include an alternative URL to which redirection should occur. If it does, a Web browser will immediately retry the alternative URL. So you never actually see a 302 error in a Web browser

以下是关于此主题的一些stackoverflow帖子。其中一些帖子描述了解决此问题的技巧。 如何在jQuery Ajax调用后管理重定向请求 JavaScript中捕获302 FOUND HTTP重定向:301(永久)vs. 302(临时)

10

针对jQuery 3及以上版本的更新 2018

我知道这是一个旧问题,但以上所有解决方案都不适用于我。以下是解决方案:

//I only created this function as I am making many ajax calls with different urls and appending the result to different divs
function makeAjaxCall(requestType, urlTo, resultAreaId){
        var jqxhr = $.ajax({
            type: requestType,
            url: urlTo
        });
        //this section is executed when the server responds with no error 
        jqxhr.done(function(){

        });
        //this section is executed when the server responds with error
        jqxhr.fail(function(){

        })
        //this section is always executed
        jqxhr.always(function(){
            console.log("getting header " + jqxhr.getResponseHeader('testHeader'));
        });
    }

请确保编写一个现有的头文件,否则将返回空/未定义值。要获取所有响应头,请使用函数getAllResponseHeaders()查看文档以获取更多信息。 - Codingwiz

10

jQuery使用的底层XMLHttpRequest对象始终会自动遵循重定向,而不是返回302状态码。因此,您无法使用jQuery的AJAX请求功能获取返回的URL。相反,您需要将所有数据放入一个表单中,并将表单提交到target属性设置为iframe的name属性的值:

$('#myIframe').attr('name', 'myIframe');

var form = $('<form method="POST" action="url.do"></form>').attr('target', 'myIframe');
$('<input type="hidden" />').attr({name: 'search', value: 'test'}).appendTo(form);

form.appendTo(document.body);
form.submit();

服务器的url.do页面将在iframe中加载,但当其返回302状态时,iframe将被重定向到最终目标。


9

尝试这个:

type: "GET",
async: false,
complete: function (XMLHttpRequest, textStatus) {
    var headers = XMLHttpRequest.getAllResponseHeaders();
}

嗯,非常感谢您的回复,但仍然返回null。还有其他想法吗? - Shane
也许你正在使用旧版本的jQuery。 - rovsen

2

+1 给 PleaseStand。

这是我的另一个黑客技巧:

在搜索并发现 "跨域 AJAX 请求" 无法从 XHR 对象获取响应标头后,我放弃了,并改用 iframe。

1. <iframe style="display:none"></iframe>
2. $("iframe").attr("src", "http://the_url_you_want_to_access")
//this is my aim!!!
3. $("iframe").contents().find('#someID').html()  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接