使用 nginx 或 kukbernetes ingress 在前端 Web 应用程序中按路径路由
Route by path in front web applications using nginx or kukbernetes ingress
假设我拥有一个域名 xxx.yyy.com,但我没有它的任何子域名 (*.xxx.yyy.com)。
所以我必须通过 path
将每个 HTTP 请求路由到其相应的服务。例如,路由 xxx.yyy.com/app1/ 到服务 app1
和 xxx.yyy.com/app2/ 到服务 app2
.
我如下配置我的 kubernestes 资源:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: xxx.yyy.com
http:
paths:
- pathType: Prefix
path: "/app1"
backend:
service:
name: app1
port:
number: 8000
- pathType: Prefix
path: "/app2"
backend:
service:
name: app2
port:
number: 8000
---
apiVersion: v1
kind: Service
metadata:
name: app1
spec:
selector:
app: app1
ports:
- protocol: TCP
port: 8000
---
apiVersion: v1
kind: Service
metadata:
name: app2
spec:
selector:
app: app2
ports:
- protocol: TCP
port: 8000
这在大多数情况下都有效,但前端 webapps 除外。
在前端 webapp 的 HTML 和 javascript 代码中,我们通过根路径 ("/") 在后端服务器上引用其资产(图像、HTTP API),就好像它已部署一样在自己的服务器上。
例如在 app1
的 javascript 代码中,我们调用 fetch('/api/getUsers')
而不是 fetch('/app1/api/getUsers')
,因此入口无法将 /api/getUsers
路由到服务app1
.
我知道通过host
而不是path
路由请求可以很容易地解决这个问题。但是我没有创建子域的权限。
那么前端webapps这种场景如何通过路由path
ingress来解决呢?
当某个路径下的浏览器可以使用 Web 应用程序时,前端请求需要以该路径为目标。您可以通过
- 只使用相对路径名,例如
api/guestUsers
而不是 /api/guestUsers
- 或在每个查询 url 前添加该路径,例如
/app1/img/logo.png
.
第二种方式支持,例如:
- 网页包:
publicPath: "/app1"
- 反应路由器:
<BrowserRouter basename="/app1"/>
- Angular:
<base href="/app1"/>
此设置可以用服务器变量动态填充,甚至 set automatically 到入口点的位置。
在您的应用程序中使用 window.location.href
并解析 URL 的第一部分并将其用作您的请求的基础。
const url = new URL(window.location.href);
const appName = url.pathname.split('/').length > 2 ? url.pathname.split('/')[1] : "";
const baseApiUrl = new URL(appName, url).toString();
fetch(baseApiUrl + '/api/getUsers')
.then((res) = {})
.catch((error) => { console.log(error)})
假设我拥有一个域名 xxx.yyy.com,但我没有它的任何子域名 (*.xxx.yyy.com)。
所以我必须通过 path
将每个 HTTP 请求路由到其相应的服务。例如,路由 xxx.yyy.com/app1/ 到服务 app1
和 xxx.yyy.com/app2/ 到服务 app2
.
我如下配置我的 kubernestes 资源:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: xxx.yyy.com
http:
paths:
- pathType: Prefix
path: "/app1"
backend:
service:
name: app1
port:
number: 8000
- pathType: Prefix
path: "/app2"
backend:
service:
name: app2
port:
number: 8000
---
apiVersion: v1
kind: Service
metadata:
name: app1
spec:
selector:
app: app1
ports:
- protocol: TCP
port: 8000
---
apiVersion: v1
kind: Service
metadata:
name: app2
spec:
selector:
app: app2
ports:
- protocol: TCP
port: 8000
这在大多数情况下都有效,但前端 webapps 除外。
在前端 webapp 的 HTML 和 javascript 代码中,我们通过根路径 ("/") 在后端服务器上引用其资产(图像、HTTP API),就好像它已部署一样在自己的服务器上。
例如在 app1
的 javascript 代码中,我们调用 fetch('/api/getUsers')
而不是 fetch('/app1/api/getUsers')
,因此入口无法将 /api/getUsers
路由到服务app1
.
我知道通过host
而不是path
路由请求可以很容易地解决这个问题。但是我没有创建子域的权限。
那么前端webapps这种场景如何通过路由path
ingress来解决呢?
当某个路径下的浏览器可以使用 Web 应用程序时,前端请求需要以该路径为目标。您可以通过
- 只使用相对路径名,例如
api/guestUsers
而不是/api/guestUsers
- 或在每个查询 url 前添加该路径,例如
/app1/img/logo.png
.
第二种方式支持,例如:
- 网页包:
publicPath: "/app1"
- 反应路由器:
<BrowserRouter basename="/app1"/>
- Angular:
<base href="/app1"/>
此设置可以用服务器变量动态填充,甚至 set automatically 到入口点的位置。
在您的应用程序中使用 window.location.href
并解析 URL 的第一部分并将其用作您的请求的基础。
const url = new URL(window.location.href);
const appName = url.pathname.split('/').length > 2 ? url.pathname.split('/')[1] : "";
const baseApiUrl = new URL(appName, url).toString();
fetch(baseApiUrl + '/api/getUsers')
.then((res) = {})
.catch((error) => { console.log(error)})