域名跳转必须在server块中用return 301实现,因server_name才能准确识别请求域名;location仅匹配路径,无法处理跨域跳转,除非是单页面精确路径跳转(如location = /old.html { return 301 /new.html; })。
直接在 location 块里用 return 301 实现域名重定向,不推荐且通常无效——因为 location 匹配的是请求路径(如 /old.html),不是整个域名;而域名跳转必须基于 server_name 判断,应在 server 块层面处理。
真正可靠的做法是:把域名级 301 跳转写在独立的 server 块中,而不是 location 里。下面说清楚怎么操作、为什么不能放 location,以及例外场景怎么处理。
Nginx 的 server_name 指令决定了哪个 server 块响应某个域名的请求。只有在这里,你才能准确捕获“用户访问的是 old-site.com”这件事。
server { listen 80; server_name old-site.com www.old-site.com; return 301 https://new-site.com$request_uri; }
location / { ... } 里写 return 301 —— 这只能跳转路径,无法改变 Host 头或协议,浏览器地址栏仍显示旧域名。原因很简单:location 是路径匹配器,它不知道请求来自哪个域名(除非配合 if ($host = ...),但 if 在 location 中受限且易出错)。
如果你只想跳转某一个 URL 路径(比如 /old.html → /new.html),这时 location 才是合适位置:
location = /old.html {return 301 /new.html;}
注意:
= 表示精确匹配,避免 /old.html?x=1 或 /old.html-bak 被误匹配return 301 https://new-site.com/new.html;
多个旧域名指向同一个新站,不用每个都写一个 server 块:
server {listen 80;server_name old1.com old2.com www.old1.com example-old.net;return 301 https://www.new-site.com$request_uri;}
$request_uri 自动保留原始路径和查询参数(如 /blog?id=123 → /blog?id=123)$host,防止 IP 直连或非法 Host 头导致跳转到 https:///xxx
别试图在监听 443 的 HTTPS server 块里加 listen 80 —— Nginx 不允许混用协议。
正确结构是两套 server:
listen 80,负责把所有 HTTP 请求 301 到 HTTPSlisten 443 ssl,提供真正的 HTTPS 服务# HTTP 入口,仅跳转server {listen 80;server_name example.com www.example.com;return 301 https://www.example.com$request_uri;}# HTTPS 服务,实际响应内容server {listen 443 ssl http2;server_name www.example.com;ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;# ... 其他配置}
配置完记得:
nginx -t 检查语法nginx -s reload 生效curl -I http://old-site.com 确认返回 301 Moved Permanently 和正确的 Location 头