基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

Nginx 中的 rewrite 和 redirect 有什么区别?

在 Nginx(以及一般的 Web 服务器)中,Rewrite(内部重写)Redirect(外部重定向) 是两个经常被混淆的概念。

简单来说,它们的核心区别在于:谁来完成地址的转换?

  • Rewrite(重写)服务器内部的行为。
  • Redirect(重定向)客户端(浏览器)的行为。

需要特别说明的是,在 Nginx 的配置文件中,rewrite 是一个具体的指令,而这个指令根据后面跟的 flag(标志位)不同,既可以实现内部重写,也可以实现外部重定向。

以下是两者的详细区别:


1. Rewrite(内部重写)

工作原理:
当客户端请求一个 URL 时,Nginx 在服务器内部将这个 URL 修改为另一个 URL,然后直接去获取修改后的 URL 对应的内容,并把内容返回给客户端。整个过程客户端完全不知道,浏览器地址栏的 URL 不会发生变化。

  • HTTP 状态码: 通常返回 200 OK
  • 网络开销: 只有一次请求和一次响应,效率高。
  • 应用场景:
    • 伪静态(Clean URLs): 将动态的、带有复杂参数的 URL(如 /article.php?id=123)伪装成友好的 URL(如 /article/123)。
    • 隐藏真实目录结构: 提高网站安全性,不暴露后端真实代码路径。
    • 单页应用(SPA)路由: 将所有请求都指向 index.html(前端路由)。
  • Nginx 指令实现: 使用 rewrite 指令,并配合 lastbreak 标志位。

Nginx 配置示例:

plaintext
# 浏览器请求 /article/123
# Nginx 内部去读取 /article.php?id=123 的内容返回,浏览器地址栏依然是 /article/123
rewrite ^/article/([0-9]+)$ /article.php?id=$1 last;

2. Redirect(外部重定向)

工作原理:
当客户端请求一个 URL 时,Nginx 服务器告诉客户端(浏览器):“你要找的内容不在这里,请去另一个地址找”。服务器会返回一个 30x 的状态码和一个 Location 响应头,浏览器收到后,会自动发起一个新的请求到目标 URL,浏览器地址栏的 URL 会发生变化。

  • HTTP 状态码: 301 Moved Permanently(永久重定向) 或 302 Found(临时重定向)。
  • 网络开销: 需要客户端发起两次请求,增加了网络延迟。
  • 应用场景:
    • 域名变更: 旧域名无缝跳转到新域名。
    • HTTP 强制跳转 HTTPS: 保证数据传输安全。
    • SEO 优化: 将多个相似的 URL 权重集中到一个 URL 上(使用 301)。
    • 页面已废弃: 旧页面下线,引导用户访问新的替代页面。
  • Nginx 指令实现: 使用 return 30x 指令(推荐),或者使用 rewrite 指令配合 redirect(302)或 permanent(301)标志位。

Nginx 配置示例:

plaintext
# 推荐做法:使用 return (性能更好)
# 浏览器请求 http://old-domain.com,浏览器地址栏会变成 https://new-domain.com
server {
    listen 80;
    server_name old-domain.com;
    return 301 https://new-domain.com$request_uri;
}

# 也可以用 rewrite 指令实现 (permanent = 301, redirect = 302)
rewrite ^/old-page$ /new-page permanent;

核心区别对比总结表

比较维度 Rewrite (内部重写) Redirect (外部重定向)
发生位置 服务器内部 客户端(浏览器)
浏览器地址栏 URL 不变 改变(变成新的 URL)
请求次数 1 次(客户端只发一次请求) 2 次(客户端收到 30x 后再发一次请求)
HTTP 状态码 200 (通常) 301, 302, 307, 308 等
执行速度 快(无额外网络开销) 相对较慢(多了一次往返网络请求)
SEO 影响 搜索引擎收录原始 URL 301 会将权重转移到新 URL
Nginx 常用标志 last, break return 301/302, permanent, redirect

最佳实践建议

  1. 如果需要改变浏览器地址栏,或者做域名/协议转换(HTTP 到 HTTPS),请使用 Redirect(优先使用 Nginx 的 return 指令,因为它的执行效率比处理正则表达式的 rewrite 更高)。
  2. 如果是为了美化 URL、隐藏后端真实路径,且不想让用户察觉,请使用 Rewrite(使用 rewrite ... last;rewrite ... break;)。
00:00
00:00