Angular 路由的 htaccess 重定向

Posted

技术标签:

【中文标题】Angular 路由的 htaccess 重定向【英文标题】:htaccess redirect for Angular routes 【发布时间】:2014-05-09 11:40:28 【问题描述】:

我有一个带有多个路由的 Angular 应用程序,例如:

site.com/
site.com/page
site.com/page/4

使用 Angular 的 html5 路由模式,当您在应用程序中单击指向它们的链接时,这些问题会正确解析,但当您进行硬刷新时,当然会出现 404 错误。为了解决这个问题,我尝试实现一个基本的 htaccess 重写。

RewriteEngine On
RewriteCond %REQUEST_FILENAME !-d
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_METHOD !OPTIONS
RewriteRule ^(.*)$ index.html [L]

这适用于角度请求,但是当我尝试在我的域中加载脚本或进行 ajax 调用时,例如:

<script src="/app/programs/script.js"></script>

此脚本未加载 - 它的请求被重定向并尝试加载 index.html 页面,因为 .htaccess 认为它​​应该重新路由请求 - 不知道此文件确实存在并且它应该加载文件而不是重定向。

有什么方法可以让 htaccess 将请求重定向到 index.html(使用视图参数),前提是它没有应该解析的实际文件?

【问题讨论】:

/app/programs/script.js 是有效文件吗? 是的,如果没有我当前的 .htaccess(如问题所示),此文件将正确解析。 这个技巧也适用于 Angular 2。 【参考方案1】:

使用类似的 sn-p:

RewriteEngine on
RewriteCond %REQUEST_FILENAME -s [OR]
RewriteCond %REQUEST_FILENAME -l [OR]
RewriteCond %REQUEST_FILENAME -d
RewriteRule ^.*$ - [NC,L]

RewriteRule ^(.*) /index.html [NC,L]

如果有,这将跳转到实际资源,对于所有 AngularJS 路由,将跳转到 index.html

【讨论】:

这几乎是完美的——它似乎无法处理带有参数的路由,例如 site.com/page/4,虽然我不知道为什么。 原来这工作正常 - 我只是有一些没有前导斜杠 (/) 的文件引用,因此试图在带有参数的路由中相对解析。 @rajasaur 非常感谢 - 这就是我喜欢 *** 的原因。帮助我快速解决了我认为我会整夜想弄清楚的问题。 你把这个 htaccess 文件放在哪里以及如何放置?? 嗨,我有http://www.domain.com/dashboard。所以网址有/dashboard 那么只有我想打开角度项目。请帮助我如何写.htaccess。其实我有2个不同的角度项目。第一个将在http://www.domain.com 上渲染,第二个应该在http://www.domain.com/dashboard 上运行。【参考方案2】:

如果应用请求directive 模板文件,但文件丢失,则会出现问题。在某些情况下,它会导致应用程序在index.html 中请求多个脚本文件。

如果文件不存在,我们应该发送404 响应而不是index.html 文件。所以我添加了简单的正则表达式模式来识别丢失的文件请求。

RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %DOCUMENT_ROOT%REQUEST_URI -f [OR]
RewriteCond %DOCUMENT_ROOT%REQUEST_URI -d
RewriteRule ^ - [L]

# If the requested pattern is file and file doesn't exist, send 404
RewriteCond %REQUEST_URI ^(\/[a-z_\-\s0-9\.]+)+\.[a-zA-Z]2,4$
RewriteRule ^ - [L,R=404]

# otherwise use history router
RewriteRule ^ /index.html

【讨论】:

如果文件不存在,而是在执行 RewriteRule ^ - [L,R=404] 时,我可以使用 RewriteRule ^ /index.htmlRewriteRule ^ - [L,R=/index.html] 重定向到 index.html 吗?我在一个应用服务器环境中,路径中断了很多。不习惯 .htaccess 中的此类更改,但只想将 404 重定向到 index.html。 是的,您可以跳过 404 部分,但有什么意义。这种.htaccess 方法适用于角度指令上缺少资产/模板文件,而不是缺少路径。如果你想处理丢失的路径,你应该自己配置路由器提供者,或者你可以使用路由器事件。 我不想要 .htaccess 的 404 句柄。我想用 index.html 角度文件处理所有这些 +1 用于给出在 RewriteCond 中使用 %DOCUMENT_ROOT 的唯一答案,这是您在 VirtualHost 中所必需的 - 否则条件永远不会成立!【参考方案3】:

穷人的解决方案(不使用 mod_rewrite):

ErrorDocument 404 /index.html

【讨论】:

【参考方案4】:

在我的情况下,我创建如下所示的 .htaccess 文件

RewriteEngine on
RewriteCond %REQUEST_FILENAME -s [OR]
RewriteCond %REQUEST_FILENAME -l [OR]
RewriteCond %REQUEST_FILENAME -d
RewriteRule ^.*$ - [NC,L]

RewriteRule ^(.*) ./index.html [NC,L]

刚刚添加。在 /index.html 之前并将该文件添加到我的域中,例如 https://example.com/subfolder,它工作正常

【讨论】:

【参考方案5】:

查看此链接:https://***.com/a/49455101/5899936 在根文件夹中创建.htaccess 文件并将其粘贴到.htaccess

 <IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %REQUEST_FILENAME !-f
  RewriteCond %REQUEST_FILENAME !-d
  RewriteRule . /index.html [L]
</IfModule>

【讨论】:

感谢它对我有用。如果是子目录,只需添加RewriteBase /SubDir而不是RewriteBase /【参考方案6】:

如果您需要,我将提供另一个详细的 htaccess 文件:

考虑 baseUrl 和默认索引文件 删除前导斜杠以管理 :params

这是我的 htaccess,非常接近,但更具体:

DirectoryIndex index.html
RewriteEngine on
RewriteBase /subDir
RewriteCond %REQUEST_FILENAME -s [OR]
RewriteCond %REQUEST_FILENAME -l [OR]
RewriteCond %REQUEST_FILENAME -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) index.html [NC,L]

【讨论】:

【参考方案7】:

julianpoemp.github.io/ngx-htaccess-generator/ 上有一个很棒的“Angular .htaccess 生成器”

生成器是开源的(源代码可以在github.com/julianpoemp/ngx-htaccess-generator找到)。

默认情况下生成的.htaccess 看起来像这样,对我来说效果很好:

# Generated with ngx-htaccess-generator v1.2.0
# Check for updates: https://julianpoemp.github.io/ngx-htaccess-generator/
#
# Transparency notice: Some parts were extracted from
# Apache Server Configs v5.0.0 | MIT License
# https://github.com/h5bp/server-configs-apache
# Extracted parts are wrapped by "START Extract from ASC"

<IfModule mod_rewrite.c>
  RewriteEngine On
  
  # Redirection of requests to index.html
  RewriteCond %DOCUMENT_ROOT%REQUEST_URI -f [OR]
  RewriteCond %DOCUMENT_ROOT%REQUEST_URI -d
  RewriteRule ^.*$ - [NC,L]
  # Redirect all non-file routes to index.html
  RewriteRule ^(?!.*\.).*$ index.html [NC,L]
</IfModule>

使用 Angular 13.0.3 成功测试。

【讨论】:

很高兴生成器对您有所帮助 :) 如果您有任何批评或改进建议,请随时在存储库页面上创建问题 :)【参考方案8】:

在我的例子中,我们需要更多的功能覆盖.htaccess 配置,例如:

强制使用 HTTPS 协议(在下面注释掉)。 将Authorization 标头转换为HTTP_AUTHORIZATION 环境变量。 跨域资源共享 (CORS)。 并禁用了特定格式的缓存(也已注释掉)。

# If mod_rewrite is not present.
<IfModule !mod_rewrite.c>
  FallbackResource /index.html
</IfModule>

<IfModule mod_rewrite.c>
  RewriteEngine On
  # Prefix for all rewritten routes ("index.html" gets "/index.html").
  RewriteBase /

  # Redirects to HTTPS protocol (once uncommented).
  #
#  RewriteCond %HTTPS !on
#  RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI [L]

  # Make sure Authorization HTTP header is available.
  RewriteRule ^ - [E=HTTP_AUTHORIZATION:%HTTP:Authorization]

  # Allows access to existing files or dirs.
  RewriteCond %REQUEST_FILENAME -s [OR]
  RewriteCond %REQUEST_FILENAME -l [OR]
  RewriteCond %REQUEST_FILENAME -d
  RewriteRule ^.*$ - [NC,L]

  # Prevents treating the main-script as a route.
  RewriteRule ^index\.html$ - [L]
  # Redirect anything else to main-script
  RewriteRule ^(.*) index.html [NC,L]
</IfModule>

# Enable Cross-Origin Resource Sharing (CORS)
#
<IfModule mod_headers.c>
  Header merge Vary Origin

  # Allows any origin (just like "*", but works in more cases)
  SetEnvIf Origin "^(http(s)?://[^/:]*(?::\d1,5)?)?" REQUEST_ORIGIN=$1
  Header always append Access-Control-Allow-Origin %REQUEST_ORIGINe env=REQUEST_ORIGIN

  Header always set Access-Control-Allow-Credentials "true"
  Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
  Header always set Access-Control-Allow-Headers "*"
  Header always set Access-Control-Expose-Headers "*"
</IfModule>

# Disables Browser caching for production (edit pattern as you wish).
#
#<FilesMatch "\.(html|htm|js|json|css)$">
#   <IfModule mod_headers.c>
#       FileETag None
#       Header unset ETag
#       Header unset Pragma
#       Header unset Cache-Control
#       Header unset Last-Modified
#       Header set Pragma "no-cache"
#       Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
#       Header set Expires "Mon, 10 Apr 1972 00:00:00 GMT"
#   </IfModule>
#</FilesMatch>

注意:我们使用[L] 而不是[L,R=301],因为后者会导致浏览器永久缓存重定向 (即使有一天该路由是一个文件,它仍然会被重定向)。

【讨论】:

以上是关于Angular 路由的 htaccess 重定向的主要内容,如果未能解决你的问题,请参考以下文章

Angular和PHP .htaccess文件重定向问题

angular---路由之重定向路由

Laravel 5 - 发布路由上的 htaccess HTTPS 重定向不起作用。

htaccess 重定向除了一个文件

Angular:手动重定向到路由

Htaccess 重定向 Laravel 4