我从Azure Web App提供Vue SPA。没有服务器端逻辑(或者与该问题无关)。
我正在HTML5历史记录模式下使用Vue Router。它真的很好。唯一的问题是,当用户尝试使用“ {” 3”等“直接” URL访问应用程序内的视图时,会发生什么。正如预期的那样,这将显示“ 404未找到”。
解决方法是众所周知的:使用URL重写将此类请求路由到应用程序的根目录:/或/index.html。
这就是我想要做的。对于Azure Web Apps,实现方法是使用web.config文件中的重写规则。我的Web.config看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Handle History Mode and custom 404/500" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
这直接从Vue路由器https://my.app.com/contacts的文档中删除。
现在访问该网站时,我会得到一个空白页。使用开发人员控制台(在Chrome中)并检查“网络”标签,我发现所有请求现在返回index.html的内容,包括脚本文件和CSS文件。
因此,重写显然很有效,只是有点过多。
问题似乎是(否定的)IsFile和IsDirectory条件。它们使用REQUEST_FILENAME服务器变量。从here可以理解,这应该是服务器文件系统上的映射路径。
所有请求都被重写时,一定是因为条件无法将路径识别为有效的文件或目录路径。
编辑:
我使用失败的请求跟踪来调试url重写,并且了解到更多信息。事实证明,当重写模块运行时,REQUEST_FILENAME
变量不正确。
在azure Web应用程序中,内容根目录位于D:\site\wwwroot
。在此文件夹中是我的应用程序的wwwroot文件夹。一些谷歌搜索发现这是预期的。另外,该映射可以正常工作-在未启用url重写的情况下,类似/img/logo.png
的url路径将返回D:\site\wwwroot\wwwroot\img\logo.png
处的静态文件。
但是当url重写模块运行时,REQUEST_FILENAME
将具有值D:\site\wwwroot\img\logo.png
。该文件不存在,因此IsFile
条件失败。
然后的问题是:为什么URL重写模块和静态文件提供程序在路径映射上不一致?
答案 0 :(得分:2)
我终于想通了。
尽管ASP.NET Core应用程序使用IIS,但它们不再允许IIS提供静态文件。静态文件保存在子目录(wwwroot)中,并由像这样在Startup.cs中配置的静态文件中间件提供服务
app.UseDefaultFiles();
app.UseStaticFiles();
静态文件中间件知道静态文件的位置(可以根据需要配置该文件),并将为指向该目录中任何文件的请求提供服务。
在Azure Web Apps中,由于历史原因,.NET Core程序集和web.config所在的内容根目录默认情况下位于D:\home\site\wwwroot
,因此请求:
http:/myapp.com/img/dang.png
中间件将检查文件:
D:\home\site\wwwroot\wwwroot\img\dang.png
存在(是的,那是两个wwwroots)。
但是,IIS没有意识到这一点。因此,就IIS而言,URL:
http:/myapp.com/img/dang.png
位于:
D:\home\site\wwwroot\img\dang.png
这就是为什么{REQUEST_FILENAME}
IIS变量没有标记的原因,以及IsFile和IsDirectory将失败的原因。
因此,总而言之:IIS URL重写在Azure Web Apps中仍然有效,但是根据url到文件的映射的任何匹配都将失败。
很高兴(我现在发现),还有一种替代方法-URL重写中间件。这是一个ASP.NET Core组件,可以作为Microsoft.AspNetCore.App
元软件包的一部分“直接使用”。它使您可以完成IIS URL重写可以完成的所有工作(以及更多操作,因为它允许使用任意编码的逻辑进行扩展),但可以使用静态文件正确处理。该文档为here。
这是我创建的重写规则:
public class Html5HistoryRewriteRule : IRule
{
private readonly string _rewriteTo;
private readonly Regex _ignore;
public Html5HistoryRewriteRule(string rewriteTo = null, string ignore = null)
{
_rewriteTo = rewriteTo ?? "/";
_ignore = ignore != null ? new Regex(ignore) : null;
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var path = request.Path.Value;
if (string.Equals(path, _rewriteTo, StringComparison.OrdinalIgnoreCase))
return;
if (_ignore != null && _ignore.IsMatch(path))
return;
var fileInfo = context.StaticFileProvider.GetFileInfo(path);
if (!fileInfo.Exists)
{
request.Path = _rewriteTo;
context.Result = RuleResult.SkipRemainingRules;
}
}
}
答案 1 :(得分:0)
我认为这是使用静态Web应用程序服务部署SPA的更方便的方法,请在此处查看有关路由的更多信息:https://docs.microsoft.com/en-us/azure/static-web-apps/routes