# 通用配置

# 定义HTTPS服务器块
server {
     # 监听443端口,启用SSL
     listen 443 ssl; 
     # 指定服务器域名
     server_name xyz.xianyu.com;
     # SSL证书文件路径
     ssl_certificate /usr/local/nginx/ssl/xyz.xianyu.com/xyz.xianyu.com.pem;
     # SSL证书私钥文件路径
     ssl_certificate_key /usr/local/nginx/ssl/xyz.xianyu.com/xyz.xianyu.com.key; 
     # SSL会话超时时间设置为5分钟
     ssl_session_timeout 5m;
     # 启用的SSL协议版本(TLSv1.2和TLSv1.3)
     ssl_protocols TLSv1.2 TLSv1.3; 
     # 允许的SSL加密套件
     ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
     # 优先使用服务器端的加密套件
     ssl_prefer_server_ciphers on;

     # 匹配根路径的所有请求
     location / {
        # 设置网站根目录
        root /web/build/bill;
        # 设置默认首页文件
        index index.html;
        # 尝试匹配文件:先找具体文件,再找目录,都找不到则返回index.html
        try_files $uri $uri/ /index.html;
     }

     # 匹配以/prod-api开头的API请求
     location /prod-api/ {
        # 反向代理到后端服务
        proxy_pass http://127.0.0.1:19001/;
        # 传递原始Host头信息
        proxy_set_header Host $host;
        # 传递客户端真实IP地址
        proxy_set_header X-Real-IP $remote_addr;
        # 传递客户端IP链(包含代理信息)
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 设置请求开始时间戳
        proxy_set_header X-Request-Start $msec;
     }
}

# 定义HTTP服务器块(用于重定向到HTTPS)
server {
     # 监听80端口(HTTP默认端口)
     listen 80;
     # 匹配相同的域名
     server_name bill.xianyu.info; 
     # 301永久重定向到HTTPS版本的相同URL
     # $host - 域名
     # $request_uri - 完整的请求URI(包含查询参数)
     return 301 https://$host$request_uri; 
}

# 关键参数解析

# location

根据URI匹配不同的处理规则

# 精确匹配 (=)

location = /api/login {}

只匹配/api/login,不匹配其他,包括/api/login/ /api/login/xyz

# 优先前缀匹配 (^~)

location ^~ /images {}

匹配以 /images开头的URI,路径级别的匹配,不是简单的字符串前缀

会匹配:

  • /images
  • /images/
  • /images/logo.png
  • /images/icons/home.svg
  • /images/gallery/

不会匹配:

  • /images1
  • /images-test
  • /myimages
  • /images123/test.jpg

匹配到后立即结束

# 正则匹配 (~ 区分大小写, ~* 不区分大小写)

location ~ \.(jpg|jpeg|png|gif)$ 
location ~* /API/

匹配到后立即结束,不再匹配其他正则

# 前缀匹配

location /api {}

匹配所有以/api开头的URI

会匹配

  • /api
  • /api/
  • /api/login
  • /apilogin
  • /api1
  • /api2
  • /api/1234
location /api/ {}

匹配所有以/api/开头的URI

会匹配

  • /api/
  • /api/1
  • /api/2
  • /api/login

不会匹配

  • /api
  • /api1

如果存在多个前缀匹配,则匹配最长的那个

# proxy_pass

proxy_pass 分为2种规则:不带URI和带URI

  • 不带URI:只包含IP和端口号,比如https://www.xianyu.info
  • 带URI:端口后带其他路径的,比如https://www.xianyu.info/ https://www.xianyu.info/api https://www.xianyu.info/api/login

以请求地址/api/login为例

请求转发到http://127.0.0.1:8080

# 不带URI

核心,一句话:保留整个请求路径,拼接到代理服务器地址后

location /api {
  proxy_pass http://localhost:8080;
}

保留请求路径/api/login,转发到http://localhost:8080/api/login

location /api/ {
  proxy_pass http://localhost:8080;
}

保留请求路径/api/login,转发到http://localhost:8080/api/login

# 带URI

核心,带/会触发Nginx的“路径替换”

移除 location 中匹配的前缀 ,然后将剩余部分拼接到 proxy_pass 的 URL 后面

一句话:保留匹配模式后的路径,拼接到代理服务器的地址后

# 例1 (正例)
location /api/ {
  proxy_pass http://localhost:8080/;
}

保留匹配模式后的路径login,拼接到proxy_pass后面,http://localhost:8080/login

# 例2 (反例)
location /api {
  proxy_pass http://localhost:8080/;
}

保留匹配模式后的路径/login,拼接到proxy_pass后面,http://localhost:8080//login

转发地址错误,出现//

# 例3 (反例)
location /api/ {
  proxy_pass http://localhost:8080/abc;
}

保留匹配模式后的路径login,拼接到proxy_pass后面,http://localhost:8080/abclogin

转发地址错误,出现abclogin

# 例4 (正例)
location /api {
  proxy_pass http://localhost:8080/abc;
}

保留匹配模式后的路径/login,拼接到proxy_pass后面,http://localhost:8080/abc/login

# 例5(正例)
location /api/ {
  proxy_pass http://localhost:8080/abc/;
}

保留匹配模式后的路径login,拼接到proxy_pass后面,http://localhost:8080/abc/login

# 例6 (反例)
location /api {
  proxy_pass http://localhost:8080/abc/;
}

保留匹配模式后的路径/login,拼接到proxy_pass后面,http://localhost:8080/abc//login

转发地址错误,出现//

可见,location和proxy_pass要不同时带/,要不同时不带/

不能一个带,一个不带

再加上location不带/时,可能会出现匹配错误的情况,比如/api会匹配到apiabc

所以建议location和proxy_pass同时带/

上次更新: 2025/10/22 15:14:11