一.问题情况
由于一台服务器文件从windows转入linux,结果发现NGINX请求的时候因为大小写敏感问题无法请求到,本来以为有个什么参数或者方法可以很快的解决问题,结果还是折腾了一下.
二.解决方法
解决方法网上介绍的差不多了.基本就就4种
1.url rewrite
2.perl模块
3.lua模块
4.ngx_http_lower_upper_case
2.1第一种只能对特定的正则或者指定地址转换,少量的这种就可以了,毕竟nginx自带.
2.2perl模块,这种也是我使用的,不过官方说使用perl时,nginx在reload可能会内存溢出不推荐使用.
首先安装perl新版(ngx的http_perl_module需要Perl5.6.1以上版本,centos7系统自带的版本不够,已经满足的可以跳过安装):http://www.cpan.org/src/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
cd /usr/local/src/ wget https://www.cpan.org/src/5.0/perl-5.36.0.tar.gz tar zxvf perl-5.36.0.tar.gz cd perl-5.36.0 #编译安装目录可以自己指定,后面修改系统perl需要用到路径 ./Configure -des -Dprefix=/usr/local/perl make #由于使用perl的程序很多所以还是先test一下比较好 make test make install #下来修改系统使用的perl,先备份一下老的 mv /usr/bin/perl /usr/bin/perl.bak #把新装的perl软链到系统目录 ln -s /usr/local/perl/bin/perl /usr/bin/perl #查看perl版本 perl -v |
make比较慢的可以根据机器CPU逻辑核心数使用 make -j {逻辑核心数} 来加快编译,如果不懂的就老老实实make
下来编译安装nginx的--with-http_perl_module,由于我用的lnmp.org的1.9版本我就按我的方法写了,用官方源码包的请自行参考
1 2 3 |
#先介绍下lnmp1.9的nginx安装 cd /usr/local/src/ wget http://soft.vpser.net/lnmp/lnmp1.9.tar.gz -cO lnmp1.9.tar.gz && tar zxf lnmp1.9.tar.gz && cd lnmp1.9 && ./install.sh nginx |
现在进入lnmp1.9的src目录找到nginx和openssl的源码包解压,然后编译指定插件就可以用了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
cd /usr/local/src/lnmp1.9/src/ tar zxvf nginx-1.22.0.tar.gz #这里解压openssl的源码是为了等下nginx编译时使用 tar zxvf openssl-1.1.1o.tar.gz cd nginx-1.22.0 #查看nginx的编译参数 nginx -V nginx version: nginx/1.22.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.1.1o 3 May 2022 TLS SNI support enabled configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-openssl=/usr/local/src/lnmp1.9/src/openssl-1.1.1o --with-openssl-opt='enable-weak-ssl-ciphers' #复制configure arguments:后的内容,在最后添加 --with-http_perl_module然后进行./configure ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-openssl=/usr/local/src/lnmp1.9/src/openssl-1.1.1o --with-openssl-opt='enable-weak-ssl-ciphers' --with-http_perl_module make make install #一定要重启服务,reload虽然不报错,但是还是没法使用perl service nginx restart #最后还要修改下lnmp.conf里的nginx编译参数附加,以免以后升级的时候少编译了模块 vim /usr/local/src/lnmp1.9/lnmp.conf Nginx_Modules_Options='--with-http_perl_module' #还有就是lnmp的脚本自带升级./upgrade.sh nginx,虽然可以完整编译nginx,但是ngx_http_perl_module会因为缺少make install步骤检测配置nginx -t会出现报错 nginx:Can't locate nginx.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .). BEGIN failed--compilation aborted. nginx: [alert] perl_parse() failed: 2 |
安装完成以后,就可以去写方法处理大小写问题了.现在http段添加一个sub方法
1 2 3 4 5 6 7 8 9 10 |
http{ …… perl_set $url ' sub { my $r = shift; my $re = lc($r->uri); return $re; } '; } |
然后在server或location里就可以使用了,这样请求的所有大写字母都会强制到小写字母地址访问
1 2 3 |
if ($uri ~ [A-Z]){ rewrite ^(.*)$ $url last; } |
但是这里遇到一个问题,如果实际的文件名不全部是小写的时候,请求地址被强制全部小写了也访问不到,所以还是需要先判断一下是否存在大写字母文件,不存在再转小写访问
1 2 3 4 5 6 7 8 9 10 |
set $test 0; if (!-f $request_filename){ set $test "${test}1"; } if ($uri ~ [A-Z]){ set $test "${test}2"; } if ($test = "012") { rewrite ^(.*)$ $url last; } |
最后还有一种问题,比如请求的是小写字母文件,但是实际文件名是大写字母的.还是无法请求.当然可以继续判断小写不存在全部转大写.但是遇到大小写混合的又不行了.所以最好的方法是把所有文件名改小写.配合强制小写访问最好,centos的rename是C的所以需要装一下perl的prename(PS:因为是windows转过来的文件不存在大小写转换以后出现重命的情况,如果是linux的文件慎用,遇到大写转小写后如果存在同名小写文件会被覆盖)
1 2 3 |
yum install epel-release yum install prename find ./ -type f -print0|xargs -0 prename 'y/A-Z/a-z/' |
这里强调一下因为很多服务都是用perl,比如DNS之类的,所以perl的任务尽可能的简单快速,以免堵塞造成系统服务不正常.
2.3lua模块
网上安装lua教程很多,有些说要用--with-ld-opt指定lua的lib库,有些是直接加入系统然后修改ld调用,反正感觉都能达到目的,lnmp.org脚本自带安装lua所以我就没去测试lua安装
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#lnmp.conf里开启lua vim lnmp.conf Enable_Nginx_Lua='y' #升级nginx ./upgrade.sh nginx #升级后nginx -V查看模块 nginx version: nginx/1.22.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.1.1o 3 May 2022 TLS SNI support enabled configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-openssl=/usr/local/src/lnmp1.9/src/openssl-1.1.1o --with-openssl-opt=enable-weak-ssl-ciphers --with-ld-opt=-Wl,-rpath,/usr/local/luajit/lib --add-module=/usr/local/src/lnmp1.9/src/lua-nginx-module-0.10.14 --add-module=/usr/local/src/lnmp1.9/src/ngx_devel_kit-0.3.1 --with-pcre=/usr/local/src/lnmp1.9/src/pcre-8.45 --with-pcre-jit |
安装完成以后看网上写的location里
1 2 3 |
if ($uri ~ [A-Z]){ rewrite_by_lua ‘return ngx.redirect(string.lower(ngx.var.uri),ngx.HTTP_MOVED_PERMANENTLY)’; } |
但是我的nginx -t会报错
nginx: [emerg] "rewrite_by_lua" directive is not allowed here in /usr/local/nginx/conf/vhost/vhosts.conf:X
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
也没找到相关解释,所以我的lua没有成功
2.4ngx_http_lower_upper_case
https://github.com/replay/ngx_http_lower_upper_case
这个我也没有去测试,但是思路写一下,先下载模块源码,然后编译成文件,然后引入nginx编译.重启nginx,然后判断请求地址有大写,再把$uri赋值给一个变量,lower处理变量到小写,然后rewrite到变量的小写地址就好了.等于替代了perl的大小写转换功能.下面是这个模块自带的说明:
1 2 3 4 5 |
set $var1 "hello"; set $var2 "WORLD"; upper $var3 "$var1 $var2"; # $var3 will be "HELLO WORLD" lower $var4 "$var1 $var2"; # $var4 will be "hello world" |