Nginx 配置笔记

18 阅读3分钟

路由匹配规则

  • 优先级:精确匹配 > 前缀匹配 > 正则匹配 > 通用匹配
  • 语法示例
    # 精确匹配 localhost/home
    location =/home {...}
    
    # 前缀匹配 localhost/api/...
    # 前缀匹配会搜索所有前缀匹配的 location, 最后返回匹配最长的 location
    location ^~/api/ {...}
    
    # 正则匹配 localhost/static/.../file.jpg
    # ~ 区分大小写,~* 不区分大小写
    # !~ 区分大小写取非,!~* 不区分大小写取非
    location ~*/repo/.+\.(gif|jpg|jpeg)$ {...}
    
    # 通用匹配 localhost/index.html
    location / {...}
    
  • 可以捕获组获取匹配结果
    # 根据环境名称设置路径
    location ^~/(staging|prod|dev)/ {
        root /dist/$1
    }
    

路径跳转:不同 location 之间跳转

  • 语法: rewrite <regex> <replacement> [flag];
    # 去除路径起始的环境名称
    location ^~/(staging|prod|dev) { 
        rewrite ^/(staging|prod|dev)/(.*)$ /$2 break; 
    }
    
  • flag 标记:
    • last :本条规则匹配完成后,不终止重写后的 url 匹配,浏览器地址栏不变
    • break :本条规则匹配完成即终止,终止重写后的 url 匹配,浏览器地址栏不变
    • redirect :返回 302 临时重定向,浏览器地址会显示跳转后的 URL 地址
    • permanent :返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址

根据环境名称设置路由

  • 文件目录结构:
    - dist
        - dev
            - index.html
            - assets
                - js/css/... 资源文件
        - prod
            - ...             
    
  • nginx 配置规则
    http {
        include mime.types;
        default_type application/octet-stream;
        # ...
        
        # 根据请求 url 获取环境名称: localhost/dev --> dev
        # 注意:map 需要位于 http {...} 中
        map $request_uri $env_name_uri {
            ~^/(staging|prod|dev)(/|$) $1;
            default "";
        }
        
        server {
            listen 443 ssl;
            server_name localhost;
            # ...
            
            # index 通过 url 获取环境名称,后续资源加载如果采用绝对路径就需要从 cookie 中获取环境名称
            set $env_name $env_name_uri;
            if ($env_name = "") {
                set $env_name $cookie_env;
            }
            add_header Set-Cookie "env=$env_name; Path=/; Max-Age=3600; HttpOnly; SameSite=Lax";
            
            # 动态设置 root 路径
            root /dist/$env_name;
            index index.html;
            
            location / {
                try_files $uri $uri/ /index.html;
            }
            
            # 处理环境特定路径, 重定向到不包含环境名称的路径
            location ^~/(staging|prod|dev) {
                rewrite ^/(staging|prod|dev)/(.*)$ /$2 break;
                try_files $uri $uri/ /index.html;
            }
            # 资源文件访问可能不会携带环境名称,从 cookie 获取环境名称
            location ^~/assets/ {
                root /dist/$env_name;
                try_files $uri $uri/ =404;
                expires 30d;
                access_log off;
                # 启用 Gzip 压缩
                gzip on;
                gzip_types text/css application/javascript image/svg+xml;
                gzip_min_length 1024;
                gzip_comp_level 6;
            }
            
            # api 根据不同环境配置不同的 host
            set $api_host "";
            if ($env_name = "staging") {
                set $api_host "http://127.0.0.1:8001";
            }
            if ($env_name = "prod") {
                set $api_host "http://127.0.0.1:8000";
            }
            location ^~/api/ {
                proxy_pass $api_host;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
            }
            
            error_page 404 /404.html;
            error_page 500 502 503 504 /50x.html;
        }
    }
    

全局变量汇总

核心请求变量说明
$args , $query_string请求中的参数(Query String),如 ?name=john 中的 name=john
$is_args如果请求有参数,值为 ?;否则为空字符串
$uri当前请求的规范化 URI‌(不含参数),如 /api/user
$request_uri完整的原始请求 URI‌(含参数),如 /api/user?name=john
$scheme请求协议(http 或 https
$request_method请求方法(GETPOST 等)
$request_length请求总长度(含请求行、请求头、请求体)
$request_body请求体内容(通常用于 proxy_pass 或日志记录)
$remote_addr客户端 IP 地址
$remote_port客户端端口号
$server_addr服务器 IP 地址
$server_port服务器端口号
$server_name匹配请求的 server 块中的 server_name 值
$host优先级顺序‌: 1. 请求行中的 Host 头 2. server_name 匹配的域名 3. 配置中首个 server_name
相应相关变量
$statusHTTP 响应状态码(如 200404
$body_bytes_sent发送给客户端的响应体字节数(不含响应头)
$bytes_sent发送给客户端的‌总字节数‌(含响应头)
$sent_http_*任意响应头的值,如 $sent_http_content_type
连接与请求控制
$connection连接序列号
$connection_requests当前连接上的请求数量(用于 keepalive 连接)
$nginx_versionNginx 版本号
时间相关变量
$time_iso8601ISO 8601 格式的本地时间(如 2023-10-05T14:31:12+08:00
$time_local普通日志格式的本地时间(如 05/Oct/2023:14:31:12 +0800
$request_time请求处理总耗时‌(单位:‌‌,精确到毫秒)
$upstream_response_time上游服务器响应耗时(单位:秒)
代理相关变量
$proxy_hostproxy_pass 指令中指定的上游主机名
$proxy_portproxy_pass 指令中指定的上游端口
$upstream_addr上游服务器的 IP 和端口(如 192.168.1.23:8080
$upstream_status上游服务器的 HTTP 响应状态码
$upstream_http_*从上游服务器返回的响应头(如 $upstream_http_server
其他实用变量
$http_*任意请求头的值$http_user_agent, $http_referer,$http_cookie
$cookie_*获取特定 Cookie 值(如 $cookie_sessionid
$arg_*获取特定 URL 参数‌(如 $arg_id 获取 ?id=123 中的 123
$document_root当前请求的 root 或 alias 指令指定的根目录路径
$realpath_root$document_root 的绝对路径(符号链接解析后)