3. Nginx web server配置

添加虚拟服务器

Nginx配置文件中至少包含一条定义虚拟服务器的server指令。当Nginx处理一个请求时,第一个被选中的虚拟服务器将用于处理该请求。

虚拟服务器通过http指令中的server指令来定义,示例如下:

http {
    server {
        # 服务器配置
    }
}

http中可以包含多条server指令来定义多个虚拟服务器。

通常server指令中会包含一条listen指令,用于指定该虚拟服务器将要监听的IP地址和端口。示例如下:

server {
    listen 127.0.0.1:8080;
    # 其他配置
}

如果不填写端口,则采用标准端口。如果不填写ip地址,则监听所有地址。如果缺少整条listen指令,则标准端口是80/tcp,默认端口是8000/tcp,由超级用户的权限决定。

如果有多个server配置了相同的ip地址和端口,Nginx会匹配server_name指令与请求头部的host字段。server_name指令的参数可以是精确的文本、通配符或正则表达式。通配符可以在字符串的头部、尾部或两端包含**可以匹配任意字符。Nginx采用Perl格式的正则表达式,以~开头。以下是一个精确匹配的例子:

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

如果有多个server_name匹配host字段,Nginx根据以下规则选择第一个相匹配的server处理请求:

  1. 精确匹配
  2. *开始的最长通配符,如*.example.org
  3. *结尾的最长通配符,如mail.*
  4. 第一个匹配的正则表达式(根据在配置文件中出现的先后顺序)

如果找不到任何与host字段相匹配的server_name,Nginx会根据请求端口将其发送给默认的server。默认server就是配置文件中第一个出现的server,也可以通过default_server指定某个server为默认server,如下所示:

server {
    listen      80 default_server;
    ...
}

配置Location指令

Nginx根据URL将请求发送给不同的代理,或处理不同的文件请求。由server指令中的location指令配置规则。

比如,可以为虚拟服务器配置三个location指令,将一些请求发送给代理服务器#1,将另外一些请求发送给代理服务器#2,再由本地文件系统处理剩余请求。

Nginx会将请求的URL匹配所有的location指令,请执行匹配location中的指令。每个location指令中通常还会包含多条更为精细匹配的location指令。

location指令包含两类参数:前缀字符串正则表达式。请求要匹配前缀字符串的话,必须以前缀字符串开始。

以下例子中location参数匹配以/some/path/开始的请求URI,如/some/path/document.html(不匹配/my-site/some/path,因为/some/path不在起始位置)。

location /some/path/ {
    ...
}

~用于匹配区分大小写的正则表达式,~*用于匹配不区分大小写的正则表达式。下面例子匹配任意包含.html.htm的URI。

location ~ \.html? {
    ...
}

Nginx先匹配前缀字符串,然后再匹配正则表达式。正则表达式拥有较高优先级,除非使用^~修饰符。在所有前缀字符串中,Nginx会挑选最精确的那个,也就是最长最匹配的那个。详细匹配过程如下:

  1. 匹配所有前缀字符串;
  2. 如果有一个=定义的精确匹配前缀字符串,停止继续匹配;
  3. 如果^~在最长匹配的前缀字符串之前,将忽略正则表达式;
  4. 存储最长的匹配前缀字符串;
  5. 匹配正则表达式;
  6. 找到第一个相匹配的正则表达,停止匹配过程,并执行该location指令;
  7. 如果没有正则表达式匹配,则使用第4部存储的最长前缀字符串;

=修饰符的典型应用是匹配 /请求。针对频繁访问/的情况,将location参数设置为= /可以加速处理过程,因为整个匹配过程在第一条之后就结束了。

location = / {
    ...
}

location指令内可以配置如何处理请求:处理静态文档或将请求转发给代理服务器。在下面的例子中,匹配第一个location的请求可以访问/data目录的文件,匹配第二个location的请求将被转发到www.example.com服务器。

server {
    location /images/ {
        root /data;
    }

    location / {
        proxy_pass http://www.example.com;
    }
}

其中root指令指定了静态文件的文件系统路径,将与请求URI一起构成静态文件的完全路径。在上述例子中,请求/images/example.png将返回服务器上位于/data/images/example.png的文件。

proxy_pass指令将请求转发到代理服务器,并将代理服务器的响应返回给客户端。在上述例子中,所有不是以/images/开头的URI请求都将被转发到代理服务器。

使用变量

通过在配置文件中使用变量,可以让Nginx以不同的方式处理请求。变量的值在运行时计算获得,并可作为参数传递给指令。变量必须以$开头。变量基于Nginx的状态定义信息,如正被处理请求的属性。

Nginx包含许多预设的变量,如core HTTP变量集,也可以使用setmapgeo指令来自定义变量。大多数变量都在运行时计算值,这些值一般都包含某个请求的相关信息。如$remote_addr包含了IP地址,而uri则包含了当前访问的URI

返回指定状态码

有些网站在处理错误或重定向时,会要求立即返回一个状态码。最简单的方式就是使用return指令,如下所示:

location /wrong/url {
    return 404;
}

return指令的第一个参数是一个状态码。第二个是可选参数,可以是重定向的URL(当状态码是301、302、303和307时),也可以是返回的文本信息。示例如下:

location /permanently/moved/url {
    return 301 http://www.example.com/moved/here;
}

locationserver中都可以包含return指令。

重写请求中的URI

在处理请求过程中,可以通过rewrite指令重复修改请求的URI。rewrite指令包含2个必填参数和1个可选参数。第一个参数是请求URI必须匹配的正则表达式。第二个参数是要替换的目标URI。第三个为可选参数,可以是一个是否继续执行后续rewrite指令的标记,也可以发送一个重定向指令(状态码是301或302)。示例如下:

location /users/ {
    rewrite ^/users/(.*)$ /show?user=$1 break;
}

locationserver中都可以包含多个rewrite指令。Nginx从上到下依次磁性rewrite指令,每次进入server指令块时,rewrite指令都会被执行一次。

Nginx执行完一系列rewrite指令后,根据最新的URI来选择location指令。如果location中也包含rewrite指令,它们也将被依次执行,执行完毕后将重新选择location

下面是一个rewritereturn联合一起使用的例子。

server {
    ...
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
    return  403;
    ...
}

这个例子用于区分两套不同的URI。类似于/download/some/media/file的URI将被改写为/download/some/mp3/file.mp3。由于最后的标识last,Nginx将忽略随后的两条指令,然后以新的URI继续处理请求。同样地,类似于/download/some/audio/file的URI将被改写为/download/some/mp3/file.ra。如果请求URI都不匹配上述两条rewrite指令,Nginx将返回403错误代码。

rewrite指令可以包含以下两种参数,用于中断处理过程:

  • last - 停止执行当前serverlocation中的rewrite指令,并以新的URI查找新的location;
  • break - 停止执行当前上下文环境内的rewrite指令,并不以新的URI查找新的location;

重写HTTP返回信息

sub_filter指令支持重写或修改HTTP请求的响应内容,如替换某个字符串。该指令支持变量和链式替换。

下例中,将指向服务器的链接改为指向代理服务器的链接:

location / {
    sub_filter      /blog/ /blog-staging/;
    sub_filter_once off;
}

另一个例子是将http请求改为https请求,并将请求头部的本地主机地址改为主机名。sub_filter_once指令用于告诉Nginx是否连续执行location中的sub_filter指令。

location / {
    sub_filter     'href="http://127.0.0.1:8080/'    'href="https://$host/';
    sub_filter     'img src="http://127.0.0.1:8080/' 'img src="https://$host/';
    sub_filter_once on;
}

注意:被sub_filter指令修改后的内容将不会再被其他sub_filter指令修改。

错误处理

error_page指令用于返回一个自定义错误页面和一个错误代码、修改响应中的错误代码或重定向到不同的URI。在下面的例子中,error_page指令返回404错误和一个错误页:

error_page 404 /404.html;

注意:该指令并不会马上返回(这是return指令做的事),仅仅指定出错时如何处理。错误代码可以能来自于代理服务器,也可能来自Nginx本身(如Nginx没有找到请求的文件)。

在下面的例子中,当Nginx未能找到请求的页面时,不会返回404,而会返回303和一个重定向到新页面指令。这通常用于处理客户端访问旧地址的情况。

location /old/path.html {
    error_page 404 =301 http:/example.com/new/path.html;
}

以下例子中,当访问一个不存在的文件时,Nginx会将请求重定向到http://backend。由于error_page指令未指定重定向代码,该代码将由重定向后的http://backend返回。

server {
    ...
    location /images/ {
        # Set the root directory to search for the file
        root /data/www;

        # Disable logging of errors related to file existence
        open_file_cache_errors off;

        # Make an internal redirect if the file is not found
        error_page 404 = /fetch$uri;
    }

    location /fetch/ {
        proxy_pass http://backend/;
    }
}

在上述例子中,当请求文件未找到时,error_page指令将发起一个内部重定向。$url变量持有当前请求的URI,并被传递给重定向。

假设请求的/images/some/file文件未找到,将被重定向到/fetch/images/some/file,同时搜索新的location。最终,请求将被第二个location处理,并被代理到http://backend

open_file_cache_errors指令可用于未找到请求文件时,禁止产生错误消息。在上述例子中可以忽略,因为错误已被正确处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容