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.html
或 RewriteRule ^ - [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
配置,例如:
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 重定向的主要内容,如果未能解决你的问题,请参考以下文章