使用Azure Web App上的Vue Router HTML5历史记录模式重写URL时遇到问题

时间:2019-09-05 10:59:26

标签: vuejs2 url-rewriting html5-history azure-webapps

我从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重写模块和静态文件提供程序在路径映射上不一致?

2 个答案:

答案 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