nginx server_name配置多个域名时的坑

 更新时间:2025年05月28日 09:20:12   作者:zzhongcy  
Nginx配置多个server_name时,$server_name默认取第一个值,导致PHP获取错误,下面就来介绍一下该问题的解决,感兴趣的可以了解一下

server_name 指令详解

server_name 指令设置基于域名的虚拟主机,⼀个ip的服务器可以配置多个域名。下⾯这些server_name是有效的:

  • server_name domain.com;
  • server_name domain.com www.domain.com;
  • server_name *.domain.com;
  • server_name .domain.com;
  • server_name domain.*;
  • server_name "";

多个域名之间以空格分隔。nginx允许⼀个虚拟主机有⼀个或多个名字,也可以使⽤通配符"*"来设置虚拟主机的名字。

server_name指令在接到请求后的匹配顺序分别为:

  • 1、准确的server_name匹配,例如:domain.com www.domain.com
  • 2、以通配符开始的字符串: .domain.com  .domain.com
  • 3、以通配符结束的字符串:www.
  • 4、匹配正则表达式:~^(?.+).domain.com$

nginx将按照1,2,3,4的顺序对server name进⾏匹配,有⼀项匹配以后就会停⽌搜索,类似于location指令。

背景

为了区分线上环境和测试环境,我弄了个自己测试专用的域名test.daemoncoder.com,线上环境的正式域名是www.daemoncoder.com。nginx里的server_name配置改为:

# 只列出了我们关心的配置,省略了其他无关部分
server {
    server_name www.daemoncoder.com test.daemoncoder.com;
    ...
}

但是使用时发现请求一直报错,重定向到错误页面,于是开始了问题的定位。

问题的定位

根据业务上报错时打的日志,定位到请求公共处理的部分里有这么一个判断:

if ($_SERVER['SERVER_NAME'] != parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) {
    $this->redirectError();
}

判断请求referer里解析出的域名如果和nginx里的$server_name变量里的域名如果不一样,就跳到错误页面,也是前面说的问题。

那么问题来了,看referer中的域名为什么和 $_SERVER['SERVER_NAME'] 不一致呢?我请求用的链接形式如 http://test.daemoncoder.com/xxx 这种形式,但是最终在PHP这一层取到 $_SERVER['SERVER_NAME'] 的值为 www.daemoncoder.com,而 HTTP_REFERER 里的域名为:test.daemoncoder.com。

可以看到 SERVER_NAME 的取值和我们的预期不一致,nginx是怎么把这个变量传过来的,需要从 nginx 的 fastcgi_params 配置文件中找一下 SERVER_NAME 的定义:

fastcgi_param SERVER_NAME $server_name;

可以看到 nginx 里的 $server_name 变量就是我们PHP里取的$_SERVER['SERVER_NAME'] 的来源。

问题的原因

通过上面的定位,我们基本可以看到问题的根本原因了(敲黑板,划重点):

当nginx配置里一个server节点下,server_name配置多个域名时,$server_name变量的值都是配置的第一个。

再回顾下我的 nginx 配置:

# 只列出了我们关心的配置,省略了其他无关部分
server {
    server_name www.daemoncoder.com test.daemoncoder.com;
    ...
}

server_name 结点有两个:www.daemoncoder.com 和 test.daemoncoder.com,当我用测试域名去访问页面的时候,可以匹配到 test.daemoncoder.com 这个域名,所以会根据当前这个server节点的配置来处理这个请求,但是 nginx 会把 $server_name 的值设置为当前 server 节点的配置的第一个 server_name,也就是 www.daemoncoder.com。如果配置改为:

server_name test.daemoncoder.com www.daemoncoder.com;

那么用测试域名请求就可以得到期望的值了(但是正式域名就出问题了)。

解决方式

第一种方式就是把配置文件按域名拆分到各自单独的server节点下,也就是:

# 省略其他无关部分
server {
    server_name www.daemoncoder.com;
    ...
}
server {
    server_name test.daemoncoder.com;
    ...
}

这样用不同的域名访问会落到各自对应的配置中,解析到的 $server_name 也都是各自的值。

第二种方式是修改 nginx SERVER_NAME 使用 $host 变量, 也就是把 

fastcgi_param SERVER_NAME $server_name;

修改为:

fastcgi_param SERVER_NAME $host;

$host变量的解析都是当前请求的host,不会受 server_name 是否配置多个域名的影响,这样我们在PHP里取 $_SERVER['SERVER_NAME'] 取出的值就是实际请求的域名,也可以解决问题(但是代码里的这个判断逻辑在测试环境似乎就没有意义了,问题不大)。

其他

有多个域名时(server_name other.domain.com www. domain.com;):fastcgi_param SERVER_NAME $server_name ,$server_name 会取值第一个域名(other.domain.com)。

$host 有可能等于 $server_name ,也可能是IP地址(直接通过访问此优先顺序取值:请求行中的主机名,或“主机”请求标头字段中的主机名,或与请求匹配的服务器名。

$1|$2|$3 ...是nginx在匹配正则时生成的变量,用于捕获一个正则表达式括号中匹配的字符串(从左到右依次存储在$1|$2|$3 ...中),新值覆盖旧值,可以使用变量保存需要用到的值set $pre $1

到此这篇关于nginx server_name配置多个域名时的坑的文章就介绍到这了,更多相关nginx server_name配置多个域名内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Windows下Nginx的启动停止重启等命令操作过程

    Windows下Nginx的启动停止重启等命令操作过程

    最近在window 上安装了nginx ,对nginx 的操作不是很熟,故在此记录一下常用操作,本文详细介绍了Windows下Nginx的启动,停止,重启等命令,需要的朋友可以参考下
    2024-03-03
  • nginx访问动态接口报错404Not Found问题解决

    nginx访问动态接口报错404Not Found问题解决

    本文主要介绍了nginx访问动态接口报错404Not Found问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 1分钟搞定Nginx版本的平滑升级与回滚的方法

    1分钟搞定Nginx版本的平滑升级与回滚的方法

    这篇文章主要介绍了1分钟搞定Nginx版本的平滑升级与回滚的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Nginx常用配置以及代理转发操作详解

    Nginx常用配置以及代理转发操作详解

    这篇文章主要给大家介绍了关于Nginx常用配置以及代理转发的相关资料,nginx一般被用来做反向代理,将请求转发到应用服务器上,比如tomcat的应用,需要的朋友可以参考下
    2023-09-09
  • nginx部署多前端项目的几种方法

    nginx部署多前端项目的几种方法

    最近一台服务器要配置多个前端项目,个人总结了3种方法来实现在一台服务器上使用nginx部署多个前端项目的方法。需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 让VIM支持Nginx .conf文件语法高亮显示功能的方法

    让VIM支持Nginx .conf文件语法高亮显示功能的方法

    这篇文章主要给大家介绍了关于让VIM支持Nginx .conf文件语法高亮显示功能的方法,文中分别介绍了手动修改和自动化脚本两种方法的实现,都给出了详细的示例代码,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-07-07
  • 详解Nginx服务器中配置超时时间的方法

    详解Nginx服务器中配置超时时间的方法

    这篇文章主要介绍了Nginx服务器中配置超时时间的方法,同时也对Nginx中的时间管理机制作了详细的介绍,需要的朋友可以参考下
    2015-12-12
  • Windows环境下Nginx 服务器 SSL 证书安装部署操作过程

    Windows环境下Nginx 服务器 SSL 证书安装部署操作过程

    这篇文章主要介绍了Windows环境下Nginx 服务器 SSL 证书安装部署,指导您如何在Windows Nginx 服务器中安装 SSL 证书,本文给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • Nginx 配置根据请求IP末段进行分流的方法

    Nginx 配置根据请求IP末段进行分流的方法

    这篇文章主要介绍了Nginx 配置根据请求IP末段进行分流的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • 从Nginx切换到Tengine的步骤分享

    从Nginx切换到Tengine的步骤分享

    由淘宝网发起的Web服务器 Tengine 可以被看作一个更好的Nginx,或者是Nginx的超集。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性
    2012-11-11

最新评论