在 Apache Tomcat 404 深层链接问题上部署 Angular 应用程序 [英] Deploy angular application on Apache Tomcat 404 deep links issue
问题描述
我正在尝试找出如何设置 Apache Tomcat 服务器来为具有深度链接的 Angular 应用程序提供服务的方法.例如:
静态服务器在收到对 mysite.com/的请求时通常会返回 index.html.但它拒绝 mysite.com/heroes/42 并返回 404 - Not Found 错误,除非它被配置为返回 index.html.
我想在 localhost/angular 上提供 angular 应用程序,我尝试了以下操作:
1) 使用以下命令构建 Angular 应用程序:
ng build --prod --base-href .
2) 将 build 文件夹的内容(默认:dist)复制到 $ApacheLocation/webapps/angular
3) 在 $ApacheLocation/conf/Catalina/localhost/rewrite.config 处添加 RewriteRules
# 如果请求现有资产或目录,请按原样转到它RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d重写规则 ^ - [L]# 如果请求的资源不存在,使用 index.html重写规则 ^\/angular\/.*$/angular/index.html
4) 在 Host 标签下方添加阀门
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve"/>
5) 启动 Tomcat 服务器并转到 localhost/angular 会给我:
未捕获的语法错误:所有 .js 包(例如 main.bundle.js)的意外标记 <
如果我不包含重写规则,tomcat 将按预期提供 localhost/angular 但会在深层链接上提供 404.
我的设置配置:
- tomcat 版本 9.0.0.M26
- 角度版本 4.4.2
- @angular/cli: 1.4.2
- 节点:8.5.0
- npm:5.4.2
- 操作系统:Linux x64
我设法解决了这个问题,例如 http://localhost:8080/angular/player/detail/4,步骤如下:
1) 使用以下命令构建 Angular 应用程序:ng build --prod -bh ./-d/angular
2) 将构建的应用程序的内容复制到 $ApacheLocation/webapps/angular
3) 重写规则:
RewriteCond %{REQUEST_PATH} !-f重写规则 ^/angular/(.*)/angular?path=$1
4) 在 app.component.ts 设置导航:
constructor(private activateRoute: ActivatedRoute, private router: Router) { }ngOnInit() {const path = this.activatedRoute.snapshot.queryParams['path'];const navigateTo = '/' + 路径;如果(路径){this.router.navigate([navigateTo]);}
}
您可以在这里找到测试项目:https://github.com/avuletica/test>
重写规则说明:
# %{REQUEST_PATH} 对应于用于映射的完整路径.# !非字符# '-f' (is regular file) 把TestString当成路径名,测试它是否存在,是否是一个普通文件.# ^ 匹配字符串或行的开头# .匹配除换行符以外的任何字符# * 匹配 0 个或多个前面的标记
所以基本上,如果/angular/anything 上没有文件,tomcat 会将完整路径作为查询字符串发送到 angular 应用程序,并从该查询参数 angular 处理路由.
I'm trying to figure out the way how to setup Apache Tomcat server to serve angular application with deep links. For example:
A static server routinely returns index.html when it receives a request for mysite.com/. But it rejects mysite.com/heroes/42 and returns a 404 - Not Found error unless it is configured to return index.html instead.
I want to serve angular app on localhost/angular, I have tried following:
1) Build angular application with:
ng build --prod --base-href .
2) Copy contents of build folder(default: dist) to $ApacheLocation/webapps/angular
3) Add RewriteRules at $ApacheLocation/conf/Catalina/localhost/rewrite.config
# 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 resource doesn't exist, use index.html
RewriteRule ^\/angular\/.*$ /angular/index.html
4) Adding valve just below Host tag
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve"/>
5) Starting Tomcat server and going to localhost/angular will give me:
Uncaught SyntaxError: Unexpected token < for all .js bundles (e.g main.bundle.js)
If I don't include rewrite rules, tomcat will serve localhost/angular as expected but will give 404 on deep links.
My setup configuration:
- tomcat version 9.0.0.M26
- angular version 4.4.2
- @angular/cli: 1.4.2
- node: 8.5.0
- npm: 5.4.2
- os: linux x64
I managed to fix this problem e.g http://localhost:8080/angular/player/detail/4 with following steps:
1) Build angular application with: ng build --prod -bh ./ -d /angular
2) Copy contents of builded app to $ApacheLocation/webapps/angular
3) Rewrite rule:
RewriteCond %{REQUEST_PATH} !-f
RewriteRule ^/angular/(.*) /angular?path=$1
4) Setup navigation at app.component.ts:
constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
ngOnInit() {
const path = this.activatedRoute.snapshot.queryParams['path'];
const navigateTo = '/' + path;
if (path) {
this.router.navigate([navigateTo]);
}
}
You can find test project here: https://github.com/avuletica/test
Explanation of rewrite rules:
# %{REQUEST_PATH} corresponds to the full path that is used for mapping.
# ! NOT character
# '-f' (is regular file) Treats the TestString as a pathname and tests whether or not it exists, and is a regular file.
# ^ matches the beginning of the string or line
# . matches any charceter except line breaks
# * match 0 or more of the preceding token
So basically if there is no file on /angular/anything tomcat sends full path as query string to angular application and from that query param angular handles routing.
这篇关于在 Apache Tomcat 404 深层链接问题上部署 Angular 应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!