0%

nginx

nginx 配置语法

  1. 配置文件由指令和指令块构成
  2. 每条指令以分号结尾,指令与参数之间以空格符合分隔
  3. 指令块以花括号将多条指令组织在一起
  4. include 指令允许组合多个配置文件以提升可维护性
  5. 使用 # 号添加注释,提高可读性
  6. 使用 $ 符号使用变量
  7. 部分指令的参数支持正则表达式

server_name

1
2
3
4
5
6
7
8
9
10
11
 # events 必须要有
events {

}

http {
server {
listen 80;
server_name localhost;
}
}

在 Nginx 配置中,server_name 的作用是用来指定匹配的主机名,即用来定义当前 server 块处理哪些请求。

具体来说,server_name 是用来匹配客户端请求中的 Host 头字段 或 URL 中的域名部分。

以下是其作用的详细解释:

匹配域名

server_name localhost; 表示当前 server 块会匹配客户端请求中 Host 头字段为 localhost 的请求。例如:客户端请求的 URL 为 http://localhost 时,Nginx 会选择这个 server 块处理请求。

虚拟主机支持

server_name 是实现 基于域名的虚拟主机 的关键。例如:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name example.com;
...
}

server {
listen 80;
server_name example.org;
...
}

当客户端访问 http://example.com 时,会由第一个 server 块处理。
当访问 http://example.org 时,会由第二个 server 块处理。

默认服务器

如果客户端的 Host 字段未匹配任何 server_name,Nginx 会选择一个默认的 server 块处理。可以通过 default_server 明确指定默认块:

1
2
3
4
5
server {
listen 80 default_server;
server_name _;
...
}

通配符和正则表达式支持

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 请求。

总结:

  1. 浏览器或 HTTP 客户端会根据用户输入的 URL 自动添加 Host 头。
  2. 服务器依赖 Host 头来区分不同的虚拟主机,尤其是在一个 IP 地址上托管多个网站时。

返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
events {}

http {

# 这里的配置能被共用
# include /etc/nginx/mime.types;

server {
listen 80;
server_name localhost;

# return 200 "hello world\n";
root /server/nginx/localhost;
index mysite.html;
}
}

可以使用 return 返回,也可以 root 指定根目录。

nginx 默认寻找 index.html 文件,可以使用 index 指令指定别的文件。

nginx 的配置文件是 /etc/nginx/nginx.conf,为了模块化,可以把不同的配置放到 /etc/nginx/conf.d/ 下面,在默认配置中包含即可。

1
2
3
4
5
events {}
http {
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/mysite.conf

1
2
3
4
5
6
7
server {
listen 80;
server_name localhost;

root /server/nginx/localhost;
index a.html;
}

location

1
2
3
4
5
6
7
8
9
server {
listen 80;
server_name localhost;

location / {
root /server/nginx/localhost;
index a.html;
}
}

使用 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/applehttp://localhost/app/other/a.html,虽然客户端变方便的了,但是会暴露一些安全问题。

locationuri 之间加上 = 号,nginx 会在完全匹配的情况下才能访问。

= 是完全匹配,~ 是正则表达式,~* 不区分大小写。

匹配优先级

  1. = 精确
  2. ^~ 优先前缀
  3. ~ 和 ~* 正则
  4. 空格普通前缀

location rewrite try_files

location return

1
2
3
4
5
6
7
8
9
server {
listen 80;
server_name localhost;

root /server/nginx/localhost;
location /temp {
return 307 /app/index.html;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ curl -i http://localhost/temp
HTTP/1.1 307 Temporary Redirect
Server: nginx/1.25.4
Date: Sat, 30 Nov 2024 11:54:06 GMT
Content-Type: text/html
Content-Length: 171
Location: http://localhost/app/index.html
Connection: keep-alive

<html>
<head><title>307 Temporary Redirect</title></head>
<body>
<center><h1>307 Temporary Redirect</h1></center>
<hr><center>nginx/1.25.4</center>
</body>
</html>

使用浏览器会自行重定向到目标页面,且地址也会变,用户是能察觉的,可以使用 rewrite 重写地址,而不是重定向。

rewrite

1
2
3
4
5
6
7
server {
listen 80;
server_name localhost;

root /server/nginx/localhost;
rewrite /temp /app/index.html;
}

此时访问,地址就不会发生变化,也没有 Location 响应头。

try_files

上面只能针对单个文件,try_files 可以匹配多个文件。

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name localhost;

root /server/nginx/localhost;

location / {
# 添加响应首部,设为访问的 uri
add_header X-debug-uri "$uri";
try_files $uri $uri/ =404;
}
}

try_files $uri $uri/ =404; 三个参数,先访问文件,在访问目录,如果有对应的目录,就访问目录下的 index.html,如果都没有就访问 404 页面,可以通过 error_page 404 /404.html;,自定义 404 页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl -i http://localhost/app/ 
HTTP/1.1 200 OK
Server: nginx/1.25.4
Date: Sat, 30 Nov 2024 12:14:23 GMT
Content-Type: text/html
Content-Length: 15
Last-Modified: Sat, 30 Nov 2024 11:15:36 GMT
Connection: keep-alive
ETag: "674af3d8-f"
X-debug-uri: /app/index.html
Accept-Ranges: bytes

hello world