我有一个带有表单的网页。当用户提交表单时,我希望服务器使浏览器重定向到表单操作的不同页面。现在,我通过使用PHP的header函数来发送302状态代码。它工作正常。
我试图让服务器上的页面以相同的方式重定向浏览器,无论它是否正常提交(没有Javascript)或通过Ajax。我尝试通过将窗口位置设置为Location头中的任何URL来实现此目的。我正在使用jQuery,并进行如下调用:
$.ajax({
url: this.action,
type: "POST",
data: getFormData(this),
complete: function(request) {
window.location.assign(request.getResponseHeader("Location"));
}
});
然而,这不起作用。在考虑之后,我意识到这并不是很令人惊讶。在Ajax请求中,浏览器应该在更改readyState之前透明地处理重定向响应,例如302代码。当完整的函数运行时,它正在查找最终目标中的Location标头而没有找到它。
作为实验,我尝试使用Location标头发送200状态代码。我尝试了Ajax请求,它工作正常。但是,当我执行非Ajax提交时,它不起作用。浏览器转到表单操作页面并停留在那里,就像它忽略了Location标题一样。
在两种情况下是否有任何方法可以使同一页面重定向,而服务器不必知道或关心请求是否是Ajax请求?
如果这很重要,我在各种浏览器(IE8,IE7,IE6,Firefox 3.5,Chrome)中尝试了表格,每次都有类似的结果。此外,我正在做一个帖子请求,以避免碰到IE的2083字符URL长度限制。
答案 0 :(得分:5)
HTTP 302 response are consumed silently by XmlHttpRequest
implementations(例如jQuery的ajax
函数)。这是一个特色。
我过去解决这个问题的方法是检测XmlHttpRequests并发出"Content-Location"
header(而不是"Location"
标头)。最常用的跨库方法是检查服务器端代码中的"X-Requested-With"
http标头(jQuery,Prototype,Mootools等设置此代码):
if (@$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
header('Content-Location: ' . $redirect_url);
} else {
header('Location: ' . $redirect_url);
}
您仍然需要特殊情况下的客户端代码:
$.ajax({
// ...
complete: function(xhr) {
var redirect_url = xhr.getResponseHeader("Content-Location");
if (redirect_url) {
window.location = redirect_url;
}
}
})
答案 1 :(得分:0)
如果用户被重定向,为什么选择Ajax?像这样的Ajax的重点是在没有页面刷新的情况下对页面进行更改,因此您使用的技术看起来有点像构建输出到碎纸机漏斗的打印机。
答案 2 :(得分:0)
我想更多地了解您的用例。从我的理解你试图让你的应用程序加载基于Ajax调用的'Location'标题的页面?我问为什么?
HTTP标头似乎是从中获取该信息的正确位置。您的应用程序本质上不是在进行“我应该在何处重定向到?”的查询。没有理由Ajax响应实际上必须使用302和“Location”标头进行响应。为什么不让它使用包含新URL的JSON或XML进行响应?
编辑:重新阅读倒数第二段。我不确定有什么好方法可以达到你想要的效果。这个概念听起来很糟糕。 :)
答案 3 :(得分:0)
将附加参数传递给您的ajax请求,以便轻松识别请求类型。当ajax - 不重定向 - 只需发送目标url,然后通过location.href重定向客户端ajax回调
像这样:$.post('/controller/action', {formdata}, function (redirect_to) { location.href = redirect_to; });
答案 4 :(得分:0)
将“完成”工作:
$.ajax({
type: frm.attr('method'),
url: frm.attr('action'),
data: frm.serialize(),
complete: complete(xhr, status) {
window.location.assign(xhr.getResponseHeader("Location"));
}
});
答案 5 :(得分:0)
您是否尝试使用错误功能而非完整?
$.ajax({
url: this.action,
type: "POST",
data: getFormData(this),
error: function(request) {
if(request.status == 302)
window.location.assign(request.getResponseHeader("Location"));
}
});
jQuery向错误函数发送任何3xx响应。也许在这个阶段仍然可以使用“位置”标题。
答案 6 :(得分:0)
为什么不让您的“ajax动作”只需填写所需的表单字段并提交表单?通过这种方式,您将获得与手动提交时完全相同的行为。
答案 7 :(得分:0)
这是另一种选择,但您需要进行一些跨浏览器测试:
complete: function(request) {
if(request.status == 200) {
var doc = document.open(request.getResponseHeader('Content-Type'));
doc.write(request.responseText);
doc.close();
}
}
主要缺点:地址栏中的URL不会改变;可能会混淆后退按钮/历史记录
虽然我认为@ crescentfresh的想法是要走的路