nginx 配置语法
- 配置文件由指令和指令块构成
- 每条指令以分号结尾,指令与参数之间以空格符合分隔
- 指令块以花括号将多条指令组织在一起
- include 指令允许组合多个配置文件以提升可维护性
- 使用 # 号添加注释,提高可读性
- 使用 $ 符号使用变量
- 部分指令的参数支持正则表达式
server_name
1 | # events 必须要有 |
在 Nginx 配置中,server_name
的作用是用来指定匹配的主机名,即用来定义当前 server
块处理哪些请求。
具体来说,server_name
是用来匹配客户端请求中的 Host
头字段 或 URL 中的域名部分。
以下是其作用的详细解释:
匹配域名
server_name localhost;
表示当前 server 块会匹配客户端请求中 Host
头字段为 localhost 的请求。例如:客户端请求的 URL 为 http://localhost
时,Nginx 会选择这个 server 块处理请求。
虚拟主机支持
server_name
是实现 基于域名的虚拟主机 的关键。例如:
1 | server { |
当客户端访问 http://example.com
时,会由第一个 server 块处理。
当访问 http://example.org
时,会由第二个 server 块处理。
默认服务器
如果客户端的 Host 字段未匹配任何 server_name
,Nginx 会选择一个默认的 server
块处理。可以通过 default_server
明确指定默认块:
1 | server { |
通配符和正则表达式支持
server_name
还支持通配符和正则匹配,以下是常见用法:
- 精确匹配:server_name example.com;
- 通配符匹配:server_name *.example.com; 匹配所有子域名,如 www.example.com。
- 正则表达式匹配:server_name ~^www.\d+.example.com$; 匹配类似 www.123.example.com 的域名。
简化配置
在测试环境中使用 server_name localhost; 是常见做法,因为测试访问时通常使用 http://localhost
。
Host 头部
Host 头部是浏览器自己加的。Host 头是由浏览器或其他 HTTP
客户端自动添加到 HTTP
请求中的,按照 HTTP/1.1
标准,它是 必需的头部字段,用于指定目标服务器的主机名。
为什么需要 Host 头?
在 HTTP/1.1
中,Host
头的引入是为了解决 虚拟主机 的问题。在一个服务器上,多个网站可以共享一个 IP 地址,服务器需要知道客户端想要访问的是哪个网站。Host 头提供了这个信息。
例如:当用户访问 http://example.com
时,浏览器会自动在请求头中加上:Host: example.com
,如果用户访问的是 http://localhost
,则请求头会变成:Host: localhost
。
浏览器如何生成 Host 头?
来源于用户输入的 URL,浏览器根据用户输入的 URL 提取主机名。例如:
- 输入
http://example.com
,Host 是example.com
。 - 输入
http://127.0.0.1:8080
,Host 是 127.0.0.1:8080 包括端口号(如果不是默认端口)
对于默认的 HTTP
端口 80 或 HTTPS
端口 443,Host 通常不包括端口号。
对于非默认端口,Host 会加上端口号。例如:
URL: http://example.com:8080
-> Host: example.com:8080
非浏览器客户端是否会添加 Host?
非浏览器的 HTTP 客户端(如 curl、wget、Postman 等)也会根据请求的 URL 自动添加 Host 头。如果没有指定,某些客户端可能会报错或者默认设置为 localhost。
如果没有 Host 头会怎样?
HTTP/1.1
请求中:必需
如果缺少 Host
头,符合标准的 HTTP/1.1
服务器会返回 400 Bad Request
错误。
HTTP/1.0
请求中:可选
在 HTTP/1.0
中,Host 头是可选的,因为那个时代,每个域名通常有一个独立的 IP 地址,虚拟主机不常见。然而,现代服务器通常仍然会要求 Host 头,即使是 HTTP/1.0 请求。
总结:
- 浏览器或 HTTP 客户端会根据用户输入的 URL 自动添加 Host 头。
- 服务器依赖 Host 头来区分不同的虚拟主机,尤其是在一个 IP 地址上托管多个网站时。
返回值
1 | events {} |
可以使用 return
返回,也可以 root
指定根目录。
nginx 默认寻找 index.html
文件,可以使用 index
指令指定别的文件。
nginx 的配置文件是 /etc/nginx/nginx.conf
,为了模块化,可以把不同的配置放到 /etc/nginx/conf.d/
下面,在默认配置中包含即可。
1 | events {} |
/etc/nginx/conf.d/mysite.conf
1 | server { |
location
1 | server { |
使用 location
指令也是可以访问的,但是如果把后面的 /
换成 /app
,那么访问 http://localhost/app
就会 404。
在 /server/nginx/localhost
下创建 app
目录,在 app
目录下创建 a.html
,再次使用 http://localhost/app
访问还是 404
,要使用 http://localhost/app/
或者 http://localhost/app/a.html
才能访问。不加 /
nginx 会把 app 当做文件处理,目录中没有对应的文件,只有目录,但是这样还会匹配 http://localhost/apple
和 http://localhost/app/other/a.html
,虽然客户端变方便的了,但是会暴露一些安全问题。
在 location
和 uri
之间加上 =
号,nginx 会在完全匹配的情况下才能访问。
=
是完全匹配,~
是正则表达式,~*
不区分大小写。
匹配优先级
- = 精确
- ^~ 优先前缀
- ~ 和 ~* 正则
- 空格普通前缀
location rewrite try_files
location return
1 | server { |
1 | curl -i http://localhost/temp |
使用浏览器会自行重定向到目标页面,且地址也会变,用户是能察觉的,可以使用 rewrite
重写地址,而不是重定向。
rewrite
1 | server { |
此时访问,地址就不会发生变化,也没有 Location
响应头。
try_files
上面只能针对单个文件,try_files
可以匹配多个文件。
1 | server { |
try_files $uri $uri/ =404;
三个参数,先访问文件,在访问目录,如果有对应的目录,就访问目录下的 index.html
,如果都没有就访问 404 页面,可以通过 error_page 404 /404.html;
,自定义 404 页面。
1 | curl -i http://localhost/app/ |