如何使用jQuery阻止Ajax请求跟随重定向


102

我使用jQuery ajax函数来访问Web服务,但是服务器不是将响应返回带有描述问题的状态码的响应,而是将请求重定向到描述问题的带有200标题的页面。我对此无法进行任何更改,因此我需要以某种方式在客户端上解决它。

示例:请求转到某个找不到的URL,因此我收到302重定向到另一个位置。发送了新请求,我收到200 OK,从而防止触发错误回调。

有什么办法可以防止ajax请求遵循重定向,而是调用回调,最好是error方法。或者,是否可以检测客户端中是否发生了重定向?



8
奇怪的是,你的后台是报告302的没有发现,而不是404
杰克Feasel

Answers:


96

我觉得您的问题很有趣,但总体而言,这个问题似乎让我更加误解。至少我将尝试解释我对问题的理解。

静默(透明)重定向是XMLHttpRequest规范的一部分(在此特别注意单词“ ...透明地跟随重定向...”)。该标准仅提及用户代理(Web浏览器)可以阻止或通知某些类型的自动重定向,但这不是的一部分XMLHttpRequest。它是HTTP客户端配置(操作系统配置)或Web浏览器配置的一部分。因此jQuery.ajax,您无法阻止重定向的任何选择。

您会看到HTTP重定向是HTTP协议的一部分,而不是的一部分XMLHttpRequest。因此,它在另一个抽象层次或网络堆栈上。例如,XMLHttpRequest可以从HTTP代理或本地浏览器缓存中检索的数据,这是HTTP协议的一部分。通常,提供数据的服务器而不是客户端会影响缓存。

您可以将问题的要求与要求进行比较,以防止在通信过程中更改Web服务器的IP地址或更改IP路由。在某些情况下,所有事情都可能很有趣,但是通信堆栈另一层又有一部分,不能由jQuery.ajax或管理XMLHttpRequest

XMLHttpRequest标准说客户端配置可以具有防止重定向的选项。对于“微软世界”(我更了解),您可以查看WinHttpSetOption函数,该函数可用于设置WINHTTP_OPTION_DISABLE_FEATURE带有WINHTTP_DISABLE_REDIRECTS值的选项。另一种方法是将WINHTTP_OPTION_REDIRECT_POLICY选项与WINHTTP_OPTION_REDIRECT_POLICY_NEVER值一起使用。Windows中可以使用的另一项功能是WinHttpSetStatusCallback函数,该函数可以设置接收一些通知的回调函数,例如WINHTTP_CALLBACK_FLAG_REDIRECT

因此,通常可以实现您的要求,但是该解决方案可能并不独立于操作系统或Web浏览器,也不在jQuery.ajax或级别上XMLHttpRequest


2
出色的答案和深刻的见解!我在curl方面有一些经验,您可以为它设置类似的标记。我希望可以将这样的指令传递给浏览器,但是从您的回答中,我知道预期的行为将是遵循重定向,就像将初始请求发送到服务器分配的位置一样。
约尔根

@Jørgen:不客气!在大多数情况下,重定向根本不是问题。您没有描述使用jQuery.ajax的上下文,也没有描述您是否完全控制向其发送请求的Web服务器。因此很难给您其他可以真正解决您问题的建议。
奥莱格

恐怕我无法控制服务器端。我猜我最好的选择是分析或验证响应内容。
约尔根

@Jørgen:在您的情况下,为什么重定向是一个问题?如果服务器临时或永久地将页面移动到另一个位置,则它可以将您的原始请求重定向到新位置。绝对可以。管理员可以将Web服务器配置为进行重定向,例如在服务器上的还原操作或任何其他支持工作期间。如果您通过具有DNS的URL询问服务器,则管理员可以将IP映射更改为另一台服务器。他可以以与DNS重新配置相同的方式执行HTTP重定向。你有什么问题?
奥莱格

我的问题是重定向转到通用错误页面。我知道服务器的设置应该不同,但是现在我需要针对这种情况找到解决方案。
约尔根

23

我不认为有可能。基础库(XHR)透明地发出新请求。话虽如此,我在这些情况下所做的(通常是会话超时类型的交易,将我带到登录页面)是发回自定义响应标头。我还设置了一个全局ajax处理程序,该处理程序检查该标头的存在,并在存在时进行适当响应(例如,将整个页面重定向到登录屏幕)。

如果您有兴趣,这里是我必须注意该自定义标头的jQuery代码:

/* redirects main window when AJAX request indicates that the session has expired on the backend. */
function checkSession(event, xhr, ajaxOptions)
{
    if (xhr.readyState == 4)
    {
        if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
        {
            window.location.href='sessionExpired.html'; //whatever
        }
    }
}

$(document).ajaxComplete(checkSession)

1
谢谢,我想我将不得不采用一种类似的方法来分析响应。
约尔根

11

我发现了一个功能,可以检查您的呼叫是否已重定向。它是xhr.state():如果被“拒绝”,则会发生重定向。

成功回调的示例:

request.success(function(data, textStatus, xhr)
{
    if(xhr.state() == "resolved")
    {
        //no redirection
    }
    if(xhr.state() == "rejected")
    {
        //redirection
    }
});

错误回调示例:

request.error(function(xhr, textStatus)
{
    if (xhr.state() == "rejected")
    {
        //redirection
        location.href = "loginpage";
    } else
    {
        //some other error happened
        alert("error");
    }
});

1
您的答案中的提示确实帮助我们成功了。为了使其他人受益,我们将WebSphere Portal的安全性与SiteMinder集成在一起。我们有一个Portlet,它需要Ajax调用到资源URL,并且超时时,它会进行透明的重定向,但是我们无处可寻如何重定向到登录页面。检查jqXHR.state()被“拒绝”肯定有帮助。再次非常感谢。
Uresh Kuruhuri 2015年

很好的发现,但是可能会出现误报,因为即使承诺被拒绝,而不仅仅是重定向,也会触发“已拒绝”状态。jQuery解释了何时发送“拒绝”状态api.jquery.com/deferred.state
Nitin

1

我可能无法增加先前已回答的编码人员的有见识的智慧,但是我将添加一个特定的案例,以供其他人了解。

我在SharePoint上下文中遇到了此302静默重定向。我有一些简单的Javascript客户端代码可对SharePoint子站点执行ping操作,如果收到200 HTTP响应,它将通过以下方式重新定位到该站点:window.location。如果它收到其他任何内容,则会向用户发出该站点不存在的通知。

但是,在网站存在但用户没有权限的情况下,SharePoint会静默重定向到AccessDenied.aspx页。SharePoint已经在服务器/服务器场级别完成了HTTP 401身份验证握手-用户可以访问SharePoint。但是我想使用某种数据库标志来处理对子站点的访问。静默重定向绕过了我的“ else”子句,因此我无法抛出自己的错误。就我而言,这不是一个止步不前-它是一致的可预测行为。但这有点令人惊讶,在此过程中我学到了一些有关HTTP请求的知识!


1

我对同一件事感兴趣,找不到Takman提到state()方法为自己做了一些挖掘。为了人们出现在这里寻找答案,以下是我的发现:

如多次所述,您不能阻止重定向,但是可以检测到它们。据MDN可以使用responseURLXMLHttpRequestObject所有重定向后,其中将包含响应来自的最终网址。唯一需要注意的是Internet Explorer不支持它(Edge拥有它)。自从xhr/ jqXHR传入success/ donejQuery的功能是实际的延伸XMLHttpRequest,它应该可以在那里。


0

我想您会收到200响应,因为第二次没有重定向,因为404页没有过期,因此将其保存在缓存中。也就是说,浏览器第二次在缓存中为您提供页面。在ajax jquery中有一个属性“ cache”。 http://api.jquery.com/jQuery.ajax/

您应该将其写为“ false”


0

虽然无法禁用XmlHttpRequests中的位置重定向,但这是在使用fetch()时

fetch('url', {redirect: manual});

提取操作不会告诉您重定向的URL是什么。您可以禁用该行为,但是“重定向:手动”并非旨在让用户自己使用名称意图来处理重定向。
lcjury

-2

我不确定这是否适用于您的情况,但是您可以编写代码以响应AJAX函数中的特定状态代码-

$.ajax({
    url: '/admin/secret/data',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    statusCode: {
        200: function (data) {
            alert('302: Occurred');
            // Bind the JSON data to the UI
        },
        401: function (data) {
            alert('401: Occurred');
            // Handle the 401 error here.
        }
    }
});

9
我不认为这也适用,因为OP说,他总是得到一个200个状态码由于重定向在后台发生的事情..
是巴里

-4

对于ajax请求,在请求标头中,您将具有以下内容

X-Requested-With    XMLHttpRequest

通过服务器端的此条件,您可以过滤请求。


他想检查响应而不是请求(已经控制了他)
是Barry

也许Gfox建议对于返回3xx的ajax请求是没有意义的,您可以过滤这种请求并返回403。如果您有一个网站提供需要表单身份验证的页面,并且这些页面也进行了ajax调用,并且您希望将授权逻辑放在一个地方,那么对我来说,这是一个有效的答案。
maciejW
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.