Wikitten的Nginx配置拾遗

作者:James Zhu ([email protected])

创建日期:2018-04-09

引言

Wikitten是一个开源PHP Wiki软件,它支持将一个目录及其子目录下的Markdown文件,通过Web页面显示出来。但是官方没有提供Nginx的配置说明,也没有虚拟目录配置说明。我不断调试Nginx站点配置,最终完成了软件配置。本文将Nginx配置中遇到的问题,及其解决原理记录下来,方便大家在以后遇到相同的问题时,少走弯路。

location官方文档

语法: location [ = | ~ | ~ | ^~ ] uri* { ... }

location @name { ... }

默认值: -

上下文: server, location

为某个请求URI(路径)建立配置。

路径匹配在URI规范化以后进行。所谓规范化,就是先将URI中形如“%XX”的编码字符进行解码,再解析URI中的相对路径“.”和“..”部分,另外还可能会压缩相邻的两个或多个斜线成为一个斜线。

可以使用前缀字符串或者正则表达式定义路径。使用正则表达式需要在路径开始添加“~*”前缀(不区分大小写),或者“~”前缀(区分大小写)。为了根据请求URI查找路径,nginx先检查前缀字符串定义的路径(前缀路径),在这些路径中找到能最精确匹配请求URI的路径。然后nginx按在配置文件中的出现顺序检查正则表达式路径,匹配上某个路径后即停止匹配并使用该路径的配置,否则使用最大前缀匹配的路径的配置。

路径可以嵌套,但有例外,后面将提到。

在不区分大小写的操作系统(诸如Mac OS X和Cygwin)上,前缀匹配忽略大小写(0.7.7)。但是,比较仅限于单字节的编码区域(one-byte locale)。

正则表达式中可以包含匹配组(0.7.40),结果可以被后面的其他指令使用。

如果最大前缀匹配的路径以“^~”开始,那么nginx不再检查正则表达式。

而且,使用“=”前缀可以定义URI和路径的精确匹配。如果发现匹配,则终止路径查找。 比如,如果请求“/”出现频繁,定义“location = /”可以提高这些请求的处理速度, 因为查找过程在第一次比较以后即结束。这样的路径明显不可能包含嵌套路径。

在0.7.1到0.8.41的所有nginx中,如果请求匹配的前缀字符串路径并没有“=”或“^~”前缀, 路径查找过程仍然会停止,而不进行正则表达式匹配。

让我们用一个例子解释上面的说法:

location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /documents/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ { 
    [ configuration E ] 
}

请求“/”匹配配置A, 请求“/index.html”匹配配置B, 请求“/documents/document.html”匹配配置C, 请求“/images/1.gif”匹配配置D, 请求“/documents/1.jpg”匹配配置E。

前缀“@”定义了命名路径。这种路径不在一般的请求处理中使用, 而是用在请求重定向中。这些路径不能嵌套,也不能包含嵌套路径。

配置实践

首先需要在site.conf中增加develop.sysom.wuxingdev.cn的虚拟目录支持

server {
    listen                80;
    server_name            develop.sysom.wuxingdev.cn;
    index                index.php;
    root                /data1/www/sysom/src;
    location ^~ /wiki/ {
        if (!-e $request_filename) {
            rewrite ^(.*) /wiki/index.php;
        }
        location = /wiki/index.php {
            fastcgi_pass   php:9000;
            fastcgi_index  index.php;
            include        fastcgi.conf;
        }
    }
    include                include/common.conf;
}

common.conf使用原有配置文件即可

location ~* \.(txt|xls|ico|htm|html|js|css|gif|jpe?g|png|zip)$ {
    access_log off;
    error_log /dev/null crit;
    log_not_found off;
    break;
}

location = /blank.html {
    alias /usr/share/nginx/html/blank.html;
    access_log off;
    break;
}

location = /favicon.ico {
    alias /usr/share/nginx/html/favicon.ico;
    access_log off;
    break;
}

location = /robots.txt {
    alias /usr/share/nginx/html/robots.txt;
    access_log off;
    break;
}

location ~ \.php$ {
    fastcgi_pass   php:9000;
    fastcgi_index  index.php;
    include        fastcgi.conf;
}

这里有几个需要注意的URL,我们一一讨论:

http://develop.sysom.wuxingdev.cn/wiki/%E7%AC%91%E5%82%B2%E6%B1%9F%E6%B9%96/%E8%99%BE%E7%B1%B3%E6%B7%B7%E6%B1%9F%E6%B9%96/AF%E7%A6%8F%E5%88%A9%E5%85%91%E6%8D%A2.md

这个URI实际文件不存在,即使存在,Markdown文件也是无法直接输出的,需要通过PHP处理,转成HTML显示。然而,匹配到wiki虚拟目录配置后,即停止进行其它正则匹配,也就无法匹配到后面“.php”的配置。因此,需要另外在wiki虚拟目录配置中加上PHP的解析,示例如下:

location ^~ /wiki/ {
    if (!-e $request_filename) {
        rewrite ^(.*) /wiki/index.php;
    }
    location = /wiki/index.php {
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        include        fastcgi.conf;
    }
}

http://develop.sysom.wuxingdev.cn/wiki/static/css/main.css

这个URI可以匹配到2个location

location ^~ /wiki/ {
    [ configuration ... ]
}
location ~* \.(txt|xls|ico|htm|html|js|css|gif|jpe?g|png|zip)$ {
    [ configuration ... ]
}

当然,如果直接把wiki放在sysom目录中的话,这2段配置任意一段都是可以工作的,不影响代码正常运行。这就要引出第3个示例URI:

http://develop.sysom.wuxingdev.cn/wiki/resource/crm/CRM-%E6%8A%A5%E5%A4%87%E6%B5%81%E7%A8%8B.png

这个URI看似和上一个相似,其实不然。上一个URI中资源是存在于代码目录下的,而这个URI中资源是存在于知识库目录下的,因此它也需要通过PHP处理,将文件内容输出显示。

因此,这里必须要求匹配到虚拟目录的location配置。在匹配到多个location的情况下,如果保证匹配到自己想要的呢?这里通过“^~”来提高优先级。

如果最大前缀匹配的路径以“^~”开始,那么nginx不再检查正则表达式。

小结

至此,Wikitten的Nginx配置已经完成。摘取一段网上对于location修饰符的总结:

(无): 如果不存在修饰符,则将该位置解释为前缀匹配。这意味着给定的位置将与请求URI的开头匹配以确定匹配项。

=: 如果使用等号,则如果请求URI与给定的位置完全匹配,则此块将被视为匹配项。

~: 如果存在波浪线,则此位置将被解释为区分大小写的正则表达式匹配。

~*: 如果使用波浪线和星号修饰符,则位置块将被解释为不区分大小写的正则表达式匹配。

^~: 如果存在脱字符和波浪线修饰符,并且如果选择此块作为最佳非正则表达式匹配,则不会进行正则表达式匹配。

外部资源

results matching ""

    No results matching ""