You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于数据库实现URL重定向时遭遇Too Many Redirects错误排查

解决URL重定向"too many redirects"问题

问题背景

实现基于数据库的URL重定向功能,redirectfrom字段存储源URL,redirectto字段存储目标URL,规则已成功存入数据库,但运行时触发"too many redirects"错误,相关代码如下:

RedirectUrl方法代码

public void RedirectUrl(string sourceUrl)
{
    using (DrWaelGhanemEntities context = new DrWaelGhanemEntities())
    {
        RedirectUrlsTable redirectRule = context.RedirectUrlsTables
            .FirstOrDefault(rule => rule.RedirectFrom == sourceUrl);

        if (redirectRule != null)
        {
            string destinationUrl = redirectRule.RedirectTo;

            // Check if the destination URL is the same as the source URL.
            if (string.Equals(sourceUrl, destinationUrl, StringComparison.OrdinalIgnoreCase))
            {
                // Handle this case to prevent a redirection loop.
                HttpContext.Current.Response.StatusCode = 404;
                HttpContext.Current.Response.End();
            }
            else
            {
                HttpContext.Current.Response.Redirect(destinationUrl, endResponse: true);
            }
        }
        else
        {
            // No matching rule found; you can handle this case as needed.
            HttpContext.Current.Response.StatusCode = 404;
            HttpContext.Current.Response.End();
        }
    }
}

Global.asax代码

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
}

protected void Application_BeginRequest(object sender, EventArgs e)
{
    UriBuilder builder = new UriBuilder(Request.Url);
    bool found = false;
    string URL = String.Empty;

    if (!HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("cpanel") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains(".axd") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("localhost") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("platform"))
    {
        if (!builder.Host.Contains("www"))
        {
            builder.Host = "www." + builder.Host;
            found = true;
        }

        URL = builder.ToString();
        URL = Server.UrlDecode(URL);
    }

    if (URL.EndsWith("/") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("cpanel") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains(".axd") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("localhost") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("platform"))
    {
        found = true;
        URL = URL + "/";
    }

    if (found && !Request.Url.IsLoopback)
    {
        Response.RedirectPermanent(URL, true);
    }
}

问题排查

1. 斜杠添加逻辑导致死循环

Application_BeginRequest中的第二个判断存在逻辑错误:当URL已经以/结尾时,代码会再次添加一个/,形成xxx.com//的URL。服务器会自动将//解析为/,触发相同逻辑再次添加斜杠,最终导致循环重定向。

2. WWW跳转与数据库规则冲突

如果数据库中存在example.com/page → www.example.com/page的规则,同时Application_BeginRequest强制将非WWW URL跳转为WWW版本,会导致请求反复触发重定向逻辑;反之,若目标URL是非WWW而WWW跳转强制转WWW,也会引发循环。

3. URL匹配不标准化

RedirectUrl中使用精确字符串匹配rule.RedirectFrom == sourceUrl,但如果传入的sourceUrl与数据库存储的URL在大小写、WWW前缀、斜杠结尾上不一致,可能导致错误匹配,触发重复重定向。

解决方案

1. 修复斜杠处理逻辑

修改Application_BeginRequest中的斜杠判断,仅当URL不以/结尾时添加斜杠:

// 替换原斜杠判断代码
if (!URL.EndsWith("/") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("cpanel") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains(".axd") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("localhost") && !HttpContext.Current.Request.Url.AbsoluteUri.ToLower().Contains("platform"))
{
    found = true;
    URL = URL + "/";
}

2. 统一URL格式,避免规则冲突

  • 存储重定向规则时,统一URL格式:要么全带WWW,要么全不带,同时统一斜杠结尾规则。
  • 调整Application_BeginRequest执行顺序:先完成WWW和斜杠标准化,再调用RedirectUrl,确保传入的sourceUrl是标准化后的格式。

3. 优化RedirectUrl匹配逻辑

添加URL标准化辅助方法,统一匹配规则,避免大小写、前缀、斜杠差异导致的错误:

public void RedirectUrl(string sourceUrl)
{
    // 标准化源URL
    string normalizedSource = NormalizeUrl(sourceUrl);
    
    using (DrWaelGhanemEntities context = new DrWaelGhanemEntities())
    {
        RedirectUrlsTable redirectRule = context.RedirectUrlsTables
            .FirstOrDefault(rule => NormalizeUrl(rule.RedirectFrom) == normalizedSource);

        if (redirectRule != null)
        {
            string destinationUrl = redirectRule.RedirectTo;
            string normalizedDest = NormalizeUrl(destinationUrl);

            // 检测直接循环
            if (normalizedSource == normalizedDest)
            {
                HttpContext.Current.Response.StatusCode = 404;
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
            else
            {
                // 使用永久重定向更利于SEO
                HttpContext.Current.Response.RedirectPermanent(destinationUrl, endResponse: false);
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
        }
        else
        {
            HttpContext.Current.Response.StatusCode = 404;
            HttpContext.Current.ApplicationInstance.CompleteRequest();
        }
    }
}

// URL标准化辅助方法
private string NormalizeUrl(string url)
{
    if (string.IsNullOrEmpty(url)) return url;
    
    Uri uri;
    if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) return url;
    
    // 统一WWW前缀(按需调整为去掉WWW)
    string host = uri.Host.StartsWith("www.") ? uri.Host : $"www.{uri.Host}";
    // 统一路径结尾斜杠
    string path = uri.AbsolutePath.EndsWith("/") ? uri.AbsolutePath : $"{uri.AbsolutePath}/";
    
    return new UriBuilder(uri.Scheme, host, uri.Port, path, uri.Query).ToString().ToLower();
}

4. 替换Response.End()避免请求终止问题

Response.End()会强制终止请求,可能引发异常,建议使用HttpContext.Current.ApplicationInstance.CompleteRequest()替代,同时保留状态码设置。

总结

核心问题来自Application_BeginRequest的错误斜杠逻辑,以及URL格式不统一导致的重定向冲突。通过修复斜杠处理、标准化URL格式、优化匹配逻辑,即可解决"too many redirects"错误。

内容的提问来源于stack exchange,提问作者Ahmed Alaa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:55:54