是否可以在发送 XMLHttpRequest-s 时阻止浏览器遵循重定向(即获取重定向状态代码并自行处理)?
不符合 XMLHttpRequest 对象的 W3C 标准(已添加强调):
如果响应是 HTTP 重定向:
如果 Location 标头传达的 URL 的来源是同源 与 XMLHttpRequest 来源和 重定向不违反无限 循环预防措施,透明 观察时遵循重定向 同源请求事件规则。
他们正在考虑将其用于未来的版本:
本规格不包括 正在开发以下功能 考虑用于未来版本 此规格:
- 禁用以下重定向的属性;
但最新规范不再提及这一点。
新的 Fetch API 支持不同的重定向处理模式:
follow
、error
和 manual
,但我找不到在取消重定向时查看新 URL 或状态代码的方法。您只需停止重定向本身,然后它看起来像一个错误(空响应)。如果这就是您所需要的,那么您就可以开始了。 对于XMLHttpRequest,您可以
HEAD
服务器并检查URL是否已更改:
var http = new XMLHttpRequest();
http.open('HEAD', '/the/url');
http.onreadystatechange = function() {
if (this.readyState === this.DONE) {
console.log(this.responseURL);
}
};
http.send();
您不会获得状态代码,但会找到新的 URL,而无需从中下载整个页面。
不,XMLHttpRequest 公开的 API 中没有任何地方允许您覆盖其自动遵循 301 或 302 的默认行为。
如果客户端在 Windows 上运行 IE,那么您可以使用 WinHTTP 来设置一个选项来防止该行为,但这是一个非常有限的解决方案。
您可以使用
responseURL
属性来获取重定向目的地或检查响应是否最终从您接受的位置获取。
我扩展了用户的答案以包含
abort()
电话。当您想要的只是重定向网址时,这似乎可以防止服务器发送太多数据。
var url = 'the url'
var http = new XMLHttpRequest();
http.open('GET', url);
http.onreadystatechange = function() {
if (this.readyState === this.DONE) {
console.log(this.responseURL)
this.abort() // This seems to stop the response
}
}
http.send()
在现实生活中,我将上面的代码包装在一个承诺中,但这使得代码难以阅读。
另外,我不明白为什么获取重定向网址需要这么困难,但这是另一个时间和地点的问题。
如果服务器使用状态代码
307
(临时重定向)发送重定向,则这可以工作(至少在 Chrome 中)。
let xhr = new XMLHttpRequest();
xhr.open("GET", "http://endpoint-that-can-return-redirect", true);
xhr.onreadystatechange = function() {
if (this.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
// server responded with headers first
// 'this.response' is still 'null' here,
// but 'this.status' is '200', not '307' as could be expected
let redirect_location = this.responseURL;
// cancel the request
this.abort();
doSomethingWithRedirectLocation(redirect_location);
}
};
xhr.onload = function(event) {
if (this.status == 200) {
// server sends actual data, not a redirect
let data = this.response; // or 'this.reponseText'
}
};
xhr.send();
无法在客户端处理重定向或 302 状态,如其他评论中所述。但是您可以阻止重定向。为此,您可以使用“XMLHttpRequest”设置请求标头“X-Requested-With” xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 这应该在打开之后、发送之前完成。下面的例子
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
reqObj.success(JSON.parse(this.responseText))
} else if (this.status != 200) {
reqObj.error(this.statusText)
}
};
xhttp.open(reqObj.type, reqObj.url, reqObj.async);
xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhttp.send();