web.config 重写规则在 Blob 存储中的 Azure 静态网站中不起作用

IT技术 asp.net reactjs azure azure-storage
2021-04-12 04:09:19

我有一个托管在 Azure blob 存储中的单页 React 应用程序,但收到请求的内容不存在。深度链接到页面时出错:

在此处输入图片说明

在存储帐户中启用了静态网站选项

在此处输入图片说明

这些文件都在 $web 容器中:

在此处输入图片说明

这包括以下带有重写规则的web.config,应该让 index.html 处理所有路由:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="React Routes" 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="/" appendQueryString="true" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

谁能看到我哪里出错了?

5个回答

如果您将 404 页面指向您的index.html. 这不是一个完美的解决方案 - 有副作用 - 但它适用于大多数情况。

在此处输入图片说明

如果您以这种方式托管 PWA 应用程序,一旦“安装”到您的手机上,它似乎无法脱机工作。
2021-05-25 04:09:19
这也帮助了我,请注意解释副作用(除了没有正确的 404?)
2021-05-31 04:09:19
最重要的副作用是 SEO 不喜欢 404。这意味着您的网站肯定不会在谷歌搜索中获得很好的排名。
2021-06-03 04:09:19
@PeterBoomsma 副作用是,当直接访问深层 url 时(例如从外部链接、书签等),该站点很可能会工作,因为返回了 index.html,但返回的 http 状态为 404。这可能不是很大问题,但这不是我个人会满意的。
2021-06-08 04:09:19
不......我已经有“错误文档路径”指向我的“index.html”文件,但是当尝试直接导航到我的 Angular 应用程序中的网页(路由)时,仍然出现 404 错误。
2021-06-18 04:09:19

Azure 存储 GPv2 中的静态网站与 Azure 应用服务不同。它只托管这些静态网页文件,包括 HTML/CSS/JavaScript 文件,其他文件可以在浏览器中处理,如图像robots.txt等。由于没有 IIS,它无法处理服务器端脚本。所以你的web.config文件改变访问路由并属于IIS的服务器端脚本是没有意义的。

实际上,您可以在 Azure 门户中看到这些字样。

为静态网站托管配置 blob 服务使您可以在存储帐户中托管静态内容。网页可能包括静态内容和客户端脚本。Azure 存储不支持服务器端脚本。 学到更多

并参考Learn more链接Static website hosting in Azure Storage

与静态网站托管相比,依赖服务器端代码的动态网站最好使用 Azure 应用服务托管。

如果需要 URL 重写功能,我建议为您的应用程序使用 Azure 应用服务。

我有带有深层链接的多语言 Angular 应用程序(应该直接访问),我执行了以下操作:

容器中的文件夹结构$web

. ru-UA
. uk
. en-US
. index.html
  1. index.html在 Azure 门户中的静态网站设置中启用 404
  2. 在你的根上index.html添加下一个代码:
<html>
<head>
<script>
 if (window.location.pathname != null) {
     const segments = window.location.pathname.split('/').filter(x => x.length > 0);
     const languages = ['ru-UA', 'uk', 'en-US'];

     if (languages.indexOf(segments[0]) >= 0)
     {
         sessionStorage.setItem('path', window.location.pathname);
         window.location = '/' + segments[0] + '/';
     } else {
         window.location = '/uk/'; // It might be your default language
     }
 }
</script>
</head>
</html>
  1. 然后,在您的 Angular 中添加以下内容:
     const spaRedirect = sessionStorage.getItem('path');
     if (spaRedirect) {
         const path = spaRedirect.split('/').filter(x => x.length > 0).slice(1).join('/'); // slice(1) to remove language segment
         await this.router.navigate(['/' + path]);
         sessionStorage.removeItem('path');
     }

现在您可以进行深层链接。

怎么运行的:

  1. 用户在浏览器中输入:www.domain.com/uk/very/deep/linkAzure
  2. 静态网站引擎找不到此类 blob 并重定向到 400,即 root index.html -> www.domain.com/index.html
  3. Rootindex.html通过pathname属性获得完整链接 并将其拆分为段。

    实际上,您可以避免按段拆分,但对我而言,这只是额外的验证步骤。

  4. 然后它index.html在适当的文件夹中重定向到特定Angular 的本地化,Angular Engine 开始为网站提供服务-> www.domain.com/uk/index.html

    请注意,您可以在此处延迟,因为您必须使用所有依赖项启动 Angular,并且只有在重定向之后

  5. 您的非常基本的组件会在 中找到一些东西sessionStorage.getItem('path'),并使基于 Angular 的重定向到深层链接。-> www.domain.com/uk/very/deep/link

虽然接受的答案是正确的,它说静态网站不能很好地处理 web.config,但使用静态网站不能做你想做的事是错误的您可以执行以下操作:

  1. 单击“Azure CDN”标签(静态网站下方)
  2. 创建一个新的 CDN 配置文件(注意选择 WEB(静态网站)链接而不是 BLOB。
  3. 在“所有资源”上输入新的 CDN 配置文件。
  4. 单击您在“概览”中看到的单个端点。
  5. 点击“规则引擎”
  6. 添加以下规则:

在此处输入图片说明

致谢:我的回答基于 Andreas Wendl 的回答,您可以在这里找到(https://stackoverflow.com/a/59974770/3231884)。我添加了一些细节,因为在检查了他的回答后,我花了几个小时才确切地了解我必须做什么。

好了,您现在可以完美地看到 Andreas 所说的屏幕

@john - Azure CDN 允许您免费使用 5 条规则,然后每条规则 1 美元 + 每百万个请求 0.60 美元docs.microsoft.com/en-us/azure/cdn/...
2021-05-23 04:09:19
我不知道@John,谢谢!这不会影响我,因为我每个月有 150 美元可花。
2021-05-31 04:09:19
优秀的解决方案!这应该是标记的解决方案。
2021-06-14 04:09:19
请注意,有 25 条规则的限制,每条规则每月收费 1 美元。
2021-06-15 04:09:19

这些解决方案都不适合我,我悲惨地开始接受我无法仅在 Azure 存储中托管我的 Angular 应用程序(使用路由)。

但是,实际上,我找到了解决方案。

您需要手动将web.config文件添加到您的src文件夹(是的,即使我们没有在 IIS 服务器上托管它)

 <configuration>
    <system.webServer>
        <rewrite>
          <rules>
            <rule name="Main Rule" 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>

...然后将此文件添加到angular.json文件中assets部分

  "architect": {
    "build": {
      "builder": "@angular-devkit/build-angular:browser",
      "options": {
        . . . 
        "assets": [
          "src/web.config"
        ],

令人震惊的是,这现在有效。

在我的 Angular 应用程序中,我可以点击各种子页面,例如

http://www.mikesapp.web.core.windows.net/Orders/List

而且,至关重要的是,我还可以打开浏览器并直接访问此网页。

这是否意味着,虽然没有记录,但 Azure 静态站点托管使用 IIS 并且您的 web.config 由于文件夹配置继承而工作?
2021-05-25 04:09:19
我已经对此进行了测试,但没有发现它有效。但是,如果存储帐户资源配置中错误文档路径选项设置为index.html或类似,404 响应将使用该文件作为其正文。对于 Angular、Next.js 等网站,这意味着页面将加载并且客户端 JavaScript 将处理路由。它会起作用,但它不会是理想的。就其value而言,Azure 静态站点的 HTTPServer标头值为“Windows-Azure-Web/1.0 Microsoft-HTTPAPI/2.0”,这可能不是 IIS。如果 blob 存储甚至不是 Windows,我也不会感到惊讶。
2021-05-27 04:09:19
我也测试了这个选项,但它不起作用
2021-05-28 04:09:19
是的,它最终部署到 $web 容器的根目录。
2021-06-18 04:09:19
你能详细说明一下吗?web.config构建后,此文件最终会在哪里它是否复制到$web容器的根目录
2021-06-19 04:09:19