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,我们一一讨论:
这个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;
}
}
这个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与给定的位置完全匹配,则此块将被视为匹配项。
~: 如果存在波浪线,则此位置将被解释为区分大小写的正则表达式匹配。
~*: 如果使用波浪线和星号修饰符,则位置块将被解释为不区分大小写的正则表达式匹配。
^~: 如果存在脱字符和波浪线修饰符,并且如果选择此块作为最佳非正则表达式匹配,则不会进行正则表达式匹配。