Nginx 之Rewrite 使用详解

文章目录
    • [1. 概述](#1. 概述)
    • [2. Rewrite 指令](#2. Rewrite 指令)
      • [2.1 指令语法](#2.1 指令语法)
      • [2.2 Flag 标记说明](#2.2 Flag 标记说明)
    • [3. Rewrite 与 Location](#3. Rewrite 与 Location)
      • [3.1 Location 分类](#3.1 Location 分类)
      • [3.2 Rewrite 和 Location 比较](#3.2 Rewrite 和 Location 比较)
    • [4. Rewrite 实际场景](#4. Rewrite 实际场景)
      • [4.1 基于域名的跳转](#4.1 基于域名的跳转)
      • [4.2 基于客户端 IP 访问跳转](#4.2 基于客户端 IP 访问跳转)
      • [4.3 基于参数匹配的跳转](#4.3 基于参数匹配的跳转)
      • [4.4 基于目录下所有 PHP 文件跳转](#4.4 基于目录下所有 PHP 文件跳转)
      • [4.5 基于最普通 URL 请求的跳转](#4.5 基于最普通 URL 请求的跳转)
    • [5. Rewrite 执行顺序](#5. Rewrite 执行顺序)
    • [6. Rewrite 与 If 指令](#6. Rewrite 与 If 指令)
    • [7. Rewrite 正则表达式](#7. Rewrite 正则表达式)
    • [8. Rewrite 指令的脚本指令](#8. Rewrite 指令的脚本指令)
    • [9. Rewrite 配置示例](#9. Rewrite 配置示例)
      • [9.1 301/302 重定向](#9.1 301/302 重定向)
      • [9.2 非 www 域名重定向到 www 域名](#9.2 非 www 域名重定向到 www 域名)
      • [9.3 URL 正则重写:简化 URL 结构](#9.3 URL 正则重写:简化 URL 结构)
    • [10. 结论](#10. 结论)

1. 概述

Nginx 的 rewrite 模块是处理 HTTP 请求过程中的一个重要功能,它允许基于 Perl 兼容正则表达式(PCRE)对用户请求的 URI 进行重写,并返回 30x 重定向跳转或按条件执行相关配置。这个模块提供了灵活的 URL 重写和重定向功能,可以用于实现友好 URL、301/302 重定向、条件重写等。

2. Rewrite 指令

2.1 指令语法

Nginx 中的 URL 重写主要依赖于 rewrite 指令,其基本语法如下:

复制代码
rewrite <regex> <replacement> [flag];
  • regex:用于匹配 URI 的正则表达式。

  • replacement:将匹配到的 URI 替换成的新 URI。

  • flag(可选):控制重写的行为,常见的标志有:

    • last:表示重新搜索新的 location 块(即继续匹配新的规则)。
    • break:停止当前 location 块中的规则匹配,执行后续指令。
    • redirect:执行临时 重定向(302)。
    • permanent:执行永久重定向(301)。
2.2 Flag 标记说明
  • last:重写请求并继续搜索 location 匹配。
  • break:重写请求并停止搜索 location 匹配。
  • redirect:返回 302 临时重定向。
  • permanent:返回 301 永久重定向。

3. Rewrite 与 Location

rewrite 指令可以在 serverlocation 块中配置。location 块只对域名后除去传递参数的字符串起作用,而 rewrite 可以对域名或参数字符串进行匹配和重写。

3.1 Location 分类
  • 普通 location:匹配特定路径。
  • 正则 location:使用正则表达式匹配路径。
  • 优先级:Nginx 会优先匹配带有正则表达式的 location,然后是最长非正则 location。
3.2 Rewrite 和 Location 比较
  • rewrite 用于重写请求 URI。
  • location 用于定义请求的处理方式。

4. Rewrite 实际场景

4.1 基于域名的跳转

将旧域名的访问重定向到新域名,同时保持参数不变。

复制代码
# 定义一个 server 块,用于处理进来的 HTTP 请求
server {
    # 监听 80 端口,即 HTTP 默认端口
    listen 80;
    
    # 指定该 server 块响应的域名,这里是 olddomain.com
    server_name olddomain.com;
    
    # 定义 location 块,匹配所有 URI(/ 表示根路径)
    location / {
        # 使用 rewrite 指令将所有请求从 olddomain.com 重定向到 newdomain.com
        # 并保持原有的请求路径和查询参数不变
        rewrite ^/(.*)$ http://newdomain.com/$1 permanent;
    }
}

这段配置的作用是将所有访问 olddomain.com 的请求通过 Nginx 重定向到 newdomain.com,并且保持请求的路径不变。permanent 标志表示这是一个永久重定向(301 状态码),告诉搜索引擎和浏览器该资源已经被永久移动到新的位置。

4.2 基于客户端 IP 访问跳转

只允许特定 IP 访问,其他 IP 重定向到维护页面。

复制代码
# 定义一个 server 块,用于处理进来的 HTTP 请求
server {
    # 监听 80 端口,即 HTTP 默认端口
    listen 80;
    
    # 指定该 server 块响应的域名,这里是 example.com
    server_name example.com;
    
    # 定义 location 块,匹配所有 URI(/ 表示根路径)
    location / {
        # 使用 if 指令进行条件判断,$remote_addr 是客户端的 IP 地址
        if ($remote_addr != '192.168.1.100') {
            # 如果客户端 IP 地址不是 '192.168.1.100',则返回 302 状态码
            # 并将请求重定向到 /maintenance.html,表示网站正在维护中
            return 302 /maintenance.html;
        }
    }
}

这段配置的作用是限制对 example.com 的访问,只允许 IP 地址为 192.168.1.100 的客户端访问所有资源,其他所有 IP 地址的访问都会被重定向到 /maintenance.html 页面,通常用于网站维护期间。这里使用的是临时重定向(302 状态码),意味着浏览器会显示新的 URL(即 /maintenance.html),但搜索引擎和缓存可能会保留原始请求的 URL。

4.3 基于参数匹配的跳转

根据请求参数进行跳转。

复制代码
# 定义一个 server 块,用于处理进来的 HTTP 请求
server {
    # 监听 80 端口,即 HTTP 默认端口
    listen 80;
    
    # 指定该 server 块响应的域名,这里是 example.com
    server_name example.com;
    
    # 定义 location 块,匹配所有 URI(/ 表示根路径)
    location / {
        # 使用 rewrite 指令进行 URL 重写
        # 正则表达式 ^/(.*)?param=value$ 匹配任何以 / 开头,后面跟着任意字符
        # 并且以 ?param=value 结尾的请求 URI
        rewrite ^/(.*)?param=value$ /new-path/$1 last;
        
        # last 标志表示重写完成后,继续搜索匹配的 location 块
        # 这里的 $1 是正则表达式中括号内匹配到的部分,即任意字符的部分
    }
}

这段配置的作用是将所有匹配特定模式的请求重写到一个新的路径。具体来说,它会查找所有以 / 开头,后面跟着任意内容,并且以 ?param=value 结尾的请求,并将这些请求重写到 /new-path/ 开头的路径下,同时保留原始请求中的路径部分(不包括查询参数)。last 标志意味着在重写后,Nginx 将继续检查其他 location 块以找到最合适的匹配项。

4.4 基于目录下所有 PHP 文件跳转

将特定目录下的所有 PHP 文件请求重写到新路径。

复制代码
# 定义一个 server 块,用于处理进来的 HTTP 请求
server {
    # 监听 80 端口,即 HTTP 默认端口
    listen 80;
    
    # 指定该 server 块响应的域名,这里是 example.com
    server_name example.com;
    
    # 定义一个 location 块,使用 ~ 表示这是一个正则表达式匹配
    # 正则表达式 .php$ 匹配以 .php 结尾的请求 URI
    location ~ .php$ {
        # 使用 rewrite 指令进行 URL 重写
        # 正则表达式 ^/(.*).php$ 匹配任何以 / 开头,后面跟着任意字符,以 .php 结尾的请求 URI
        rewrite ^/(.*).php$ /new-path/$1.php last;
        
        # last 标志表示重写完成后,继续搜索匹配的 location 块
        # 这里的 $1 是正则表达式中括号内匹配到的部分,即除去 .php 后缀的文件名部分
    }
}

这段配置的作用是将所有请求 URI 以 .php 结尾的请求重写到 /new-path/ 下的相同文件名。例如,请求 /example.com/about.php 会被重写为 /example.com/new-path/about.phplast 标志意味着在重写后,Nginx 将继续检查其他 location 块以找到最合适的匹配项,而不是立即停止处理当前 location 块。

4.5 基于最普通 URL 请求的跳转

将普通 URL 请求重写到新路径。

复制代码
# 定义一个 server 块,用于处理进来的 HTTP 请求
server {
    # 监听 80 端口,即 HTTP 默认端口
    listen 80;
    
    # 指定该 server 块响应的域名,这里是 example.com
    server_name example.com;
    
    # 定义 location 块,匹配所有 URI(/ 表示根路径)
    location / {
        # 使用 rewrite 指令进行 URL 重写
        # 正则表达式 ^/(.*)$ 匹配任何以 / 开头,后面跟着任意字符的请求 URI
        rewrite ^/(.*)$ /new-path/$1 permanent;
        
        # permanent 标志表示这是一个永久重定向(301 状态码)
        # 告诉浏览器和搜索引擎该资源已经被永久移动到新的位置
        # $1 是正则表达式中括号内匹配到的部分,即除去第一个斜杠后的整个请求路径
    }
}

这段配置的作用是将所有访问 example.com 的请求重定向到 /new-path/ 下的相同路径。例如,请求 /example.com/about 会被永久重定向到 /example.com/new-path/aboutpermanent 标志意味着这是一个永久重定向,浏览器会更新收藏夹中的 URL,搜索引擎也会更新其索引。

5. Rewrite 执行顺序

rewrite 指令的执行顺序如下:

  1. 执行 server 块里面的 rewrite 指令。
  2. 执行 location 匹配。
  3. 执行选定 location 中的 rewrite 指令。

6. Rewrite 与 If 指令

if 指令用于条件判断,可以与 rewrite 结合使用,但需要注意 if 是邪恶的,因为它可能导致 Nginx 配置变得复杂和难以维护。推荐使用 rewrite 来实现条件重写。

7. Rewrite 正则表达式

Nginx 的 rewrite 模块支持 PCRE 正则表达式,以下是一些常用的正则表达式元字符:

  • .:匹配任意单个字符。
  • ^:匹配字符串的开始。
  • $:匹配字符串的结束。
  • *:匹配前面的元素 0 次或多次。
  • +:匹配前面的元素 1 次或多次。
  • ?:匹配前面的元素 0 次或 1 次。
  • []:匹配括号内的任意一个字符。
  • |:逻辑或操作符。

8. Rewrite 指令的脚本指令

rewrite 模块提供了类似脚本语言的指令,可以在 HTTP 请求处理过程中对 URI 进行更灵活的操作控制。

9. Rewrite 配置示例

以下是一些 rewrite 配置的示例:

9.1 301/302 重定向
复制代码
# 定义一个 server 块,用于处理 HTTP 请求
server {
    # 监听 80 端口,这是 HTTP 协议的默认端口
    listen 80;
    
    # 指定 server 块服务的域名,这里是 olddomain.com
    server_name olddomain.com;
    
    # 定义 location 块,用于匹配所有请求的 URI(/ 表示根路径)
    location / {
        # 使用 rewrite 指令进行 URL 重写
        # 正则表达式 ^/(.*)$ 匹配所有以 / 开头的请求 URI
        rewrite ^/(.*)$ http://newdomain.com/$1 permanent;
        # 将匹配到的请求重写到 newdomain.com 的相同路径
        # $1 表示正则表达式中括号内匹配到的部分,即除了根斜杠外的路径部分
        # permanent 标志表示这是一个永久重定向(301 状态码)
        # 告诉浏览器和搜索引擎该资源已经被永久移动到新域名
    }
}

这段配置的作用是将所有访问 olddomain.com 的请求永久重定向到 newdomain.com 的相同路径。例如,如果用户访问 olddomain.com/about,他们将被重定向到 newdomain.com/about。这个重定向是永久的,意味着搜索引擎和浏览器会更新相应的链接,并且用户浏览器的地址栏也会显示新的 URL。

9.2 非 www 域名重定向到 www 域名
复制代码
# 第一个 server 块,用于处理对 example.com 的非 www 前缀域名的请求
server {
    # 监听 80 端口,这是 HTTP 协议的默认端口
    listen 80;
    
    # 指定 server 块服务的域名,这里是 example.com(没有 www 前缀)
    server_name example.com;
    
    # 对于所有请求,返回一个 301 永久重定向响应
    # 这会将用户从 http://example.com 重定向到 http://www.example.com,并保留原始请求的 URI
    return 301 http://www.example.com$request_uri;
}

# 第二个 server 块,用于处理对 www.example.com 的请求
server {
    # 监听 80 端口,这是 HTTP 协议的默认端口
    listen 80;
    
    # 指定 server 块服务的域名,这里是 www.example.com(带有 www 前缀)
    server_name www.example.com;
    
    # 定义 location 块,用于匹配所有请求的 URI(/ 表示根路径)
    location / {
        # 这里可以放置处理 www.example.com 域名请求的配置
        # 例如,可以配置 proxy_pass 来代理请求,或者 root 指令来指定文件根目录等
        # 正常站点配置
    }
}

这段配置的作用是将所有对 example.com(没有 www 前缀)的 HTTP 请求永久重定向到 www.example.com(带有 www 前缀)。第一个 server 块监听 example.com 并返回一个 301 状态码,将请求重定向到 www.example.com,同时保留请求的 URI。第二个 server 块则处理对 www.example.com 的请求,可以在这里进行进一步的配置,比如设置代理、静态文件服务等。

关于您提到的网址 http://www.example.com$request_uri,由于网络原因,解析并没有成功。这可能是由于链接格式不正确或者网络连接问题。请检查网页链接的合法性,并在确保网络连接正常的情况下适当重试。如果问题依旧存在,可能需要进一步的网络诊断或联系网站管理员。如果您有其他问题或需要帮助,请随时告知。

9.3 URL 正则重写:简化 URL 结构
复制代码
# 定义一个 server 块,用于处理进来的 HTTP 请求
server {
    # 监听 80 端口,即 HTTP 默认端口
    listen 80;
    
    # 指定该 server 块响应的域名,这里是 example.com
    server_name example.com;
    
    # 定义一个 location 块,匹配请求 URI 路径以 /category/id/ 开头的请求
    location /category/id/ {
        # 使用 rewrite 指令进行 URL 重写
        # 正则表达式 ^/category/id/(d+)$ 匹配以 /category/id/ 开头,接着是数字的请求 URI
        rewrite ^/category/id/(d+)$ /category/$1 last;
        
        # last 标志表示重写完成后,继续搜索匹配的 location 块
        # $1 是正则表达式中括号内匹配到的部分,即 URI 中的数字部分
    }
}

这段配置的作用是将所有匹配 /category/id/ 路径并且后面跟着数字的请求重写到 /category/ 路径下。例如,请求 /category/id/123 会被重写为 /category/123last 标志意味着在重写后,Nginx 将继续检查其他 location 块以找到最合适的匹配项。这样做可以允许 Nginx 在重写请求后,根据新的 URI 再次检查是否有更具体的 location 匹配,从而应用更具体的配置。

10. 结论

Nginx 的 rewrite 模块提供了强大的 URL 重写和重定向功能,可以用于实现各种复杂的 URL 处理需求。通过合理配置 rewrite 指令,可以提高网站的可用性、改善 SEO、实现域名迁移等。本手册详细介绍了 rewrite 的命令、语法、含义、环境和示例,希望能够帮助用户更好地理解和使用 Nginx 的 rewrite 功能。

相关推荐
ulias2121 天前
Linux系统中的权限问题
linux·运维·服务器
青花瓷1 天前
Ubuntu下OpenClaw的安装(豆包火山API版)
运维·服务器·ubuntu
问简1 天前
docker 镜像相关
运维·docker·容器
Dream of maid1 天前
Linux(下)
linux·运维·服务器
齐鲁大虾1 天前
统信系统UOS常用命令集
linux·运维·服务器
Benszen1 天前
Docker容器化技术实战指南
运维·docker·容器
ZzzZZzzzZZZzzzz…1 天前
Nginx 平滑升级:从 1.26.3 到 1.28.0,用户无感知
linux·运维·nginx·平滑升级·nginx1.26.3·nginx1.28.0
一叶知秋yyds1 天前
Ubuntu 虚拟机安装 OpenClaw 完整流程
linux·运维·ubuntu·openclaw
斯普信云原生组1 天前
Prometheus 环境监控虚机 Redis 方案(生产实操版)
运维·docker·容器
safestar20122 天前
ES批量写入性能调优:BulkProcessor 参数详解与实战案例
java·大数据·运维·jenkins