Nginx 根据请求参数转发
今天在测试的时候有个需求:想根据 URL 中 query 参数访问不同的环境,另外页面发起的请求也可以根据 Header 中的参数反向代理到不同的环境的服务。
下面是基于 Docker compose 的示例。
示例代码
目录结构
my-project/
├── docker-compose.yml
├── nginx/
│ ├── nginx.conf
│ └── conf.d/
│ └── default.conf
├── backend-8080/
│ └── index.html
└── backend-8084/
└── index.html
└── backend-test/
└── index.html
docker-compose.yml
yaml
version: '3.8'
services:
nginx:
image: nginx:stable-alpine3.17-slim
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d/:/etc/nginx/conf.d/:ro
depends_on:
- backend-8080
- backend-8084
- backend-test
backend-8080:
image: nginx:stable-alpine3.17-slim
volumes:
- ./backend-8080/index.html:/usr/share/nginx/html/index.html:ro
# 端口 8080 不需要暴露到主机,仅用于内部服务间通信(如果需要调试可以保留)
# ports:
# - "8080:80"
backend-8084:
image: nginx:stable-alpine3.17-slim
volumes:
- ./backend-8084/index.html:/usr/share/nginx/html/index.html:ro
# 端口 8084 不需要暴露到主机,仅用于内部服务间通信(如果需要调试可以保留)
# ports:
# - "8084:80"
backend-test:
image: nginx:stable-alpine3.17-slim
volumes:
- ./backend-test/index.html:/usr/share/nginx/html/index.html:ro
# 端口 8085 不需要暴露到主机,仅用于内部服务间通信(如果需要调试可以保留)
# ports:
# - "8085:80"
nginx.conf
这个是 nginx 默认的配置文件,一般不需要修改。
nginx
user nginx;
worker_processes auto;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
conf.d/default.conf
这个是具体的转发配置,主要是通过 $arg_{query-key}
获取请求参数,通过 $http_{header-key}
获取请求头。
注意:并发量大的可能会对性能有一定的影响。
nginx
server {
listen 80;
location / {
if ($arg_skuId = "1001") {
proxy_pass http://backend-8084;
break;
}
if ($arg_skuId = "1002") {
return 302 http://www.liujiajia.me$is_args$args;
}
if ($http_x_env = "test") {
proxy_pass http://backend-test;
break;
}
proxy_pass http://backend-8080;
}
}
另外两个 HTML 页面就随便写点文字,区分一下就可以了。
相关命令
启动:
bash
docker compose up -d
重启:
bash
docker compose restart
下面是可以通过 VS Code 插件 REST Client 测试用的示例:
http
### 8080
GET http://localhost/?a=1&b=2&skuId=1000
### 8084
GET http://localhost/?a=1&b=2&skuId=1001
### 302
GET http://localhost/?a=1&b=2&skuId=1002
### test
GET http://localhost/?a=1&b=2&skuId=1000
x-env: test