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

IT技术 javascript jquery
2021-02-25 07:27:19

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

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

有什么方法可以阻止 ajax 请求跟随重定向,而是调用回调,最好是错误方法。或者,是否可以检测客户端中是否发生了重定向?

6个回答

我觉得你的问题很有趣,但整个问题在我看来更像是一个误解。至少我会试着解释我对这个问题的理解。

无声(透明)重定向是XMLHttpRequest规范的一部分(请参阅此处特别是“...透明地跟随重定向...”)。该标准仅提到用户代理(Web 浏览器)可以防止或通知某些类型的自动重定向,但它不是XMLHttpRequest. 它是 HTTP 客户端配置(操作系统配置)或 Web 浏览器配置的一部分。所以jQuery.ajax没有任何可以阻止重定向的选项。

您可以看到 HTTP 重定向是 HTTP 协议的一部分,而不是XMLHttpRequest. 所以它位于另一个抽象级别或网络堆栈上。例如,XMLHttpRequest可以从 HTTP 代理或本地浏览器缓存中检索来自 的数据,它是 HTTP 协议的一部分。大多数情况,提供数据的服务器而不是客户端会影响缓存。

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

XMLHttpRequest标准说,客户端配置能够具有防止重定向选项。对于我更了解的“Microsoft world”,您可以查看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

@Jørgen:为什么在您的情况下重定向有问题?如果服务器临时或永久地移动了另一个位置上的某个页面,它可以将您的原始请求重定向到新位置。绝对没问题。管理员可以配置 Web 服务器以进行重定向,例如在服务器上的恢复操作或任何其他支持工作期间。如果您通过具有 DNS 的 URL 询问服务器,管理员可以将 IP 映射更改为另一台服务器。他可以以与 DNS 重新配置相同的方式进行 HTTP 重定向。你有什么问题?
2021-04-20 07:27:19
我的问题是重定向转到通用错误页面。我知道服务器应该以不同的方式设置,但现在我需要为这种情况找到解决方案。
2021-04-20 07:27:19
@Jørgen:不客气!在大多数情况下,重定向根本不是问题。您没有描述使用 jQuery.ajax 的上下文以及您是否可以完全控制向其发送请求的 Web 服务器。所以很难给你其他的建议来真正解决你的问题。
2021-05-05 07:27:19
我不控制服务器端,恐怕。我想我最好的选择是分析或验证响应内容。
2021-05-07 07:27:19
出色的答案,具有深刻的洞察力!我对 curl 有一些经验,您可以设置与您提到的类似的标志。我希望可以将此类指令传递给浏览器,但是从您的回答中,我了解到预期的行为是遵循重定向,就像将初始请求发送到服务器分配的位置一样。
2021-05-10 07:27:19

我不相信这是可能的。底层库 (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)
谢谢,我想我将不得不采用类似的方法,分析响应。
2021-04-20 07:27:19

我发现了一个功能来检查您的呼叫是否已被重定向。它是 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");
    }
});
很棒的发现,但是可能会出现误报,因为即使Promise被拒绝而不仅仅是重定向,也会触发“拒绝”状态。jQuery 解释何时发送“拒绝”状态api.jquery.com/deferred.state
2021-04-28 07:27:19
您回答中的提示确实帮助我们使事情顺利进行。为了便于其他人注意,我们将 WebSphere Portal 的安全性与 SiteMinder 集成在一起。我们有一个需要 Ajax 调用资源 url 的 portlet,当它超时时,它会发生透明重定向,但我们无处知道如何重定向到登录页面。检查 jqXHR.state() 被“拒绝”肯定有帮助。再次非常感谢。
2021-05-10 07:27:19

我不可能补充以前做出回应的编码人员的洞察力,但我会添加一个其他人可能会觉得有用的特定案例。

我在 SharePoint 上下文中遇到了这个 302 静默重定向。我有一些简单的 Javascript 客户端代码可以 ping 一个 SharePoint 子站点,如果它收到 200 HTTP 响应,它会通过window.location. 如果它收到任何其他信息,它会通知用户该站点不存在。

但是,在站点存在但用户没有权限的情况下,SharePoint 会以静默方式重定向到 AccessDenied.aspx 页面。SharePoint 已经在服务器/场级别完成了 HTTP 401 身份验证握手 - 用户可以访问 SharePoint。但是我想使用某种数据库标志来处理对子站点的访问。静默重定向绕过了我的“else”子句,所以我不能抛出我自己的错误。在我的情况下,这不是一个表演障碍 - 它是一致的可预测行为。不过有点意外,在这个过程中学到了一些关于HTTP请求的知识!

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

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