URL 重写中间件 ASP.Net Core 2.0
URL Rewriting Middleware ASP.Net Core 2.0
我无法正确编写 URL 重写中间件。我认为正则表达式是正确的。我是第一次使用这个功能,可能有些不懂。
示例urls:
http://localhost:55830/shop/alefajniealsdnoqwwdnanxc!@#lxncqihen41j2ln4nkzcbjnzxncas?valueId=116
http://localhost:55830/shop/whatever?valueId=116
http://localhost:55830/shop/toquestionmark?valueId=116
正则表达式:
\/shop\/([^\/?]*)(?=[^\/]*$)
启动,配置:
var rewrite = new RewriteOptions().AddRewrite(
@"\/shop\/([^\/?]*)(?=[^\/]*$)",
"/shop/",
true
);
app.UseRewriter(rewrite);
也许与其他方法相关的顺序有问题?
控制器:
[Route(RouteUrl.Listing + RouteUrl.Slash + "{" + ActionFilter.Value + "?}", Name = RouteUrl.Name.ShopBase)]
public ActionResult Index(string value, int valueId)
{
return View();
}
例如,当我重定向到:
我想这样显示url:
基于这篇文章:
https://www.softfluent.com/blog/dev/Page-redirection-and-URL-Rewriting-with-ASP-NET-Core
When you develop a web application, you often need to add some
redirection rules. The most common redirection rules are: redirect
from "http" to "https", add "www", or move a website to another
domain. URL rewriting is often use to provide user friendly URL.
我想解释一下重定向和重写的区别。重定向向客户端发送 HTTP 301 或 302,告诉客户端它应该使用另一个 URL 访问该页面。浏览器将更新地址栏中可见的 URL,并使用新的 URL 发出新请求。另一方面,重写发生在服务器上,是一个 URL 到另一个的翻译。服务器将使用新的 URL 来处理请求。客户端不知道服务端改写了URL.
使用 IIS,您可以使用 web.config
文件定义重定向和重写规则或使用 RewritePath
:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to https">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="Off" />
<add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
<add input="{HTTP_HOST}" negate="true" pattern="localhost" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
但是,这不再适用于 ASP.NET Core。相反,您可以使用新的 NuGet 包:Microsoft.AspNetCore.Rewrite (GitHub)。这个包非常容易使用。打开 startup.cs 文件并编辑 Configure 方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ISiteProvider siteProvider)
{
app.UseRewriter(new RewriteOptions()
.AddRedirectToHttps()
.AddRedirect(@"^section1/(.*)", "new/", (int)HttpStatusCode.Redirect)
.AddRedirect(@"^section2/(\d+)/(.*)", "new//", (int)HttpStatusCode.MovedPermanently)
.AddRewrite("^feed$", "/?format=rss", skipRemainingRules: false));
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
The rules are based on regex and substitutions. The regex is evaluated
on the HttpContext.Request.Path, which does not include the domain,
nor the protocol. This means you cannot redirect to another domain or
add "www" using this method, but don't worry, I will show you how to
do this after!
Microsoft 已决定帮助您使用这个新程序包。事实上,如果你已经有一个 web.config 文件甚至一个 .htaccess 文件(.net core 是跨平台的)你可以直接导入它们:
app.UseRewriter(new RewriteOptions()
.AddIISUrlRewrite(env.ContentRootFileProvider, "web.config")
.AddApacheModRewrite(env.ContentRootFileProvider, ".htaccess"));
如果您有无法使用正则表达式表达的复杂规则,您可以编写自己的规则。规则是实现 Microsoft.AspNetCore.Rewrite.IRule:
的 class
// app.UseRewriter(new RewriteOptions().Add(new RedirectWwwRule()));
public class RedirectWwwRule : Microsoft.AspNetCore.Rewrite.IRule
{
public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
public bool ExcludeLocalhost { get; set; } = true;
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var host = request.Host;
if (host.Host.StartsWith("www", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
if (ExcludeLocalhost && string.Equals(host.Host, "localhost", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
string newPath = request.Scheme + "://www." + host.Value + request.PathBase + request.Path + request.QueryString;
var response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = newPath;
context.Result = RuleResult.EndResponse; // Do not continue processing the request
}
}
我的问题的解决方案比看起来要简单。我承认我之前不知道我可以将 POST 与 GET:
结合起来
View: - 强类型部分视图 @model MainNavigationArchon
<form asp-controller="@Model.Controller" asp-action="@RouteUrl.Index" asp-route-value="@AureliaCMS.Infrastructure.Helpers.StringHelper.RemoveDiacritics(Model.Value.ToLower())" method="post">
<input type="hidden" asp-for="@Model.ValueId" />
<button class="btn btn-link">@Model.Value</button>
</form>
控制器:
[Route("shop" + RouteUrl.Slash + "{value}", Name = RouteUrl.Name.ShopBase)]
public ActionResult Index(int valueId)
{
return View();
}
Url 包含:
shop
来自路由属性
shoes
来自 asp-route-value
和 ?valueId=116
通过 hidden
字段发送 asp-for="@Model.ValueId"
结果:
我正在发送类似 http://localhost:55830/shop/shoes?valueId=116
的内容并显示 http://localhost:55830/shop/shoes
我无法正确编写 URL 重写中间件。我认为正则表达式是正确的。我是第一次使用这个功能,可能有些不懂。
示例urls:
http://localhost:55830/shop/alefajniealsdnoqwwdnanxc!@#lxncqihen41j2ln4nkzcbjnzxncas?valueId=116
http://localhost:55830/shop/whatever?valueId=116
http://localhost:55830/shop/toquestionmark?valueId=116
正则表达式:
\/shop\/([^\/?]*)(?=[^\/]*$)
启动,配置:
var rewrite = new RewriteOptions().AddRewrite(
@"\/shop\/([^\/?]*)(?=[^\/]*$)",
"/shop/",
true
);
app.UseRewriter(rewrite);
也许与其他方法相关的顺序有问题?
控制器:
[Route(RouteUrl.Listing + RouteUrl.Slash + "{" + ActionFilter.Value + "?}", Name = RouteUrl.Name.ShopBase)]
public ActionResult Index(string value, int valueId)
{
return View();
}
例如,当我重定向到:
我想这样显示url:
基于这篇文章: https://www.softfluent.com/blog/dev/Page-redirection-and-URL-Rewriting-with-ASP-NET-Core
When you develop a web application, you often need to add some redirection rules. The most common redirection rules are: redirect from "http" to "https", add "www", or move a website to another domain. URL rewriting is often use to provide user friendly URL.
我想解释一下重定向和重写的区别。重定向向客户端发送 HTTP 301 或 302,告诉客户端它应该使用另一个 URL 访问该页面。浏览器将更新地址栏中可见的 URL,并使用新的 URL 发出新请求。另一方面,重写发生在服务器上,是一个 URL 到另一个的翻译。服务器将使用新的 URL 来处理请求。客户端不知道服务端改写了URL.
使用 IIS,您可以使用 web.config
文件定义重定向和重写规则或使用 RewritePath
:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to https">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="Off" />
<add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
<add input="{HTTP_HOST}" negate="true" pattern="localhost" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
但是,这不再适用于 ASP.NET Core。相反,您可以使用新的 NuGet 包:Microsoft.AspNetCore.Rewrite (GitHub)。这个包非常容易使用。打开 startup.cs 文件并编辑 Configure 方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ISiteProvider siteProvider)
{
app.UseRewriter(new RewriteOptions()
.AddRedirectToHttps()
.AddRedirect(@"^section1/(.*)", "new/", (int)HttpStatusCode.Redirect)
.AddRedirect(@"^section2/(\d+)/(.*)", "new//", (int)HttpStatusCode.MovedPermanently)
.AddRewrite("^feed$", "/?format=rss", skipRemainingRules: false));
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
The rules are based on regex and substitutions. The regex is evaluated on the HttpContext.Request.Path, which does not include the domain, nor the protocol. This means you cannot redirect to another domain or add "www" using this method, but don't worry, I will show you how to do this after!
Microsoft 已决定帮助您使用这个新程序包。事实上,如果你已经有一个 web.config 文件甚至一个 .htaccess 文件(.net core 是跨平台的)你可以直接导入它们:
app.UseRewriter(new RewriteOptions()
.AddIISUrlRewrite(env.ContentRootFileProvider, "web.config")
.AddApacheModRewrite(env.ContentRootFileProvider, ".htaccess"));
如果您有无法使用正则表达式表达的复杂规则,您可以编写自己的规则。规则是实现 Microsoft.AspNetCore.Rewrite.IRule:
的 class// app.UseRewriter(new RewriteOptions().Add(new RedirectWwwRule()));
public class RedirectWwwRule : Microsoft.AspNetCore.Rewrite.IRule
{
public int StatusCode { get; } = (int)HttpStatusCode.MovedPermanently;
public bool ExcludeLocalhost { get; set; } = true;
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var host = request.Host;
if (host.Host.StartsWith("www", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
if (ExcludeLocalhost && string.Equals(host.Host, "localhost", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.ContinueRules;
return;
}
string newPath = request.Scheme + "://www." + host.Value + request.PathBase + request.Path + request.QueryString;
var response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] = newPath;
context.Result = RuleResult.EndResponse; // Do not continue processing the request
}
}
我的问题的解决方案比看起来要简单。我承认我之前不知道我可以将 POST 与 GET:
结合起来View: - 强类型部分视图 @model MainNavigationArchon
<form asp-controller="@Model.Controller" asp-action="@RouteUrl.Index" asp-route-value="@AureliaCMS.Infrastructure.Helpers.StringHelper.RemoveDiacritics(Model.Value.ToLower())" method="post">
<input type="hidden" asp-for="@Model.ValueId" />
<button class="btn btn-link">@Model.Value</button>
</form>
控制器:
[Route("shop" + RouteUrl.Slash + "{value}", Name = RouteUrl.Name.ShopBase)]
public ActionResult Index(int valueId)
{
return View();
}
Url 包含:
shop
来自路由属性
shoes
来自 asp-route-value
和 ?valueId=116
通过 hidden
字段发送 asp-for="@Model.ValueId"
结果:
我正在发送类似 http://localhost:55830/shop/shoes?valueId=116
的内容并显示 http://localhost:55830/shop/shoes