当 url 响应状态代码为 400 时如何使用 C# .Net Core 5 Blazor 服务器端应用程序中的中间件重定向到主页

Posted

技术标签:

【中文标题】当 url 响应状态代码为 400 时如何使用 C# .Net Core 5 Blazor 服务器端应用程序中的中间件重定向到主页【英文标题】:How to redirect to homepage when url response status code is 400 using middleware in C# .Net Core 5 Blazor Server Side App 【发布时间】:2021-10-06 06:47:45 【问题描述】:

我正在尝试访问返回 400 状态代码的页面,然后通过中间件将用户重定向到主页。这是一个会抛出 400 的示例 url:https://testsite.com/%C3%85%C2%81%C3%83%C2%B3d%C3%85%C2%BA_Voivodeship

请注意,将“/%C3%85%C2%81%C3%83%C2%B3d%C3%85%C2%BA_Voivodeship”附加到您的 blazor 服务器端 app/.net mvc 应用程序上的请求将抛出400 错误。

提到的 URL 与许多其他返回 400 状态代码的 URL 一起存在于站点地图中。在实际有用的环境中,仅仅从站点地图中删除网址是不够的,因为搜索引擎已经阅读了它们并将继续请求它们。除了这个 SEO 问题之外,还有一个明显的但不幸的是没有提到足够多的用户体验,即提供“错误的请求 - 无效的 URL” HTTP 错误 400。请求 URL 无效。”任何面向用户的应用程序的错误消息。这只会让用户陷入困境。

因此,确实需要在请求时处理此问题,以便将用户更正到他们可以做某事的位置,并帮助抓取网站的搜索引擎强烈指示不应抓取特定网址不再通过重定向(是的,对于那些不了解技术 SEO 的人,这是处理这种情况的正确、最佳实践方法)。

我试图通过在 Startup.cs 的 Configure 方法中放置一个 app.use 来实现这一点,但如果您使用上面提到的 url,它实际上不会命中代码。我能够打破;但是,对于任何普通请求,例如 200 状态代码一。因此,这似乎不是正确的方法。有什么想法吗?

 app.Use(async (context, next) =>
            
                var statusCode = context.Response.StatusCode;

                // Redirect to homepage of site when 400 status code
                if (statusCode == 400)
                
                    context.Response.Redirect("/");
                    return;   // short circuit
                
                await next();
            );

【问题讨论】:

传递给app.Use的lambda表达式是否必须是async 也许吧。虽然我正在为如何编写它而苦苦挣扎。 嗯,去掉asyncawait 不能这么简单 非常感谢您愿意提供帮助 【参考方案1】:

HTTP 状态码 400 和相应的消息由 HTTP.SYS 生成。 HTTP.SYS 执行 URL 验证并可以拒绝请求。在这种情况下,返回的网页看起来像

错误请求 - 无效网址


HTTP 错误 400。请求 URL 无效。

由于指定的 URL 被 HTTP.SYS 阻止,请求永远不会到达应用程序。请参阅类似的问题%09 in a URL causes IIS (HTTP.SYS?) to return HTTP 400 immediately 了解更多详情。在当前情况下,HTTP.SYS 不喜欢 %81、%83、%85 字符。 相应的消息可以在位于 %SystemRoot%\System32\LogFiles\HTTPERR 的 HTTP.SYS 日志中找到。

如果由于某种原因无法更改 URL,则 HTTP.SYS 行为可以通过 Http.sys registry settings for Windows 文章中所述位于 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters 下的 AllowRestrictedChars DWORD 注册表项进行配置。

如果非零,Http.sys 接受解码为 U+0000 - U+001F 和 U+007F - U+009F 范围的请求 URL 中的十六进制转义字符。

必须重新启动 HTTP 服务才能使更改生效。

除了 HTTP.SYS 配置更改之外,中间件代码还需要一些改进。 next 委托的执行需要移到方法的最顶部。

app.Use(
  async (context, next) =>
  
    await next();

    if (context.Response.StatusCode == 400)
    
      context.Response.Redirect("/");
    
  );

另外,正如 cmets 中提到的,中间件的位置很重要。 HttpResponse.Redirect 方法只是将 HTTP 状态代码设置为 301302 并指定 Location 标头。如果其他中间件或应用程序代码已经向客户端发送了响应,HttpResponse.Redirect 方法将抛出异常。

【讨论】:

【参考方案2】:

中间件是否执行取决于中间件的定位。如果你把它放在其他中间件之后,它们就会短路它。

如果您希望此中间件始终执行,请将其放在其他中间件之上,并在调用 next 后放置您的自定义代码

 app.Use(async (context, next) =>
        
           
            // Call next first and then apply your custom code
            await next();

            var statusCode = context.Response.StatusCode;

            // Redirect to homepage of site when 400 status code
            if (statusCode == 400)
            
                context.Response.Redirect("/");
                return;   // short circuit
            
           
        );

【讨论】:

无效。我部分不同意您关于中间件代码定位的说法,因为特定的状态代码 400 无论位置如何都不会触发。 请将var statusCode = context.Response.StatusCode; 行移到await next(); 下。下一个委托执行实际的工作,状态代码将仅在其执行后更新。在执行请求之前捕获当前实现状态代码并将其存储到局部变量中。 我做了更改,没有效果。

以上是关于当 url 响应状态代码为 400 时如何使用 C# .Net Core 5 Blazor 服务器端应用程序中的中间件重定向到主页的主要内容,如果未能解决你的问题,请参考以下文章

如何自定义响应错误 400 错误请求

我尝试使用 passport.js 对用户进行身份验证,但它给了我一个错误**服务器响应状态为 400(错误请求)**

如何获取返回 Http 状态代码 406 或 400 的 API 的响应 JSON

服务器响应状态为 400 () Laravel 和 Vue js?

POST / PUT 上的 Java Spring REST API 状态 400 响应

http常见的状态码,400,401,403状态码 , http响应 ,php设置http响应