nginx作为反向代理服务器的时候,如果端口设置的特殊,在重定向的时候可能遇到问题。当然可以通过在代码中redirect一个绝对地址来规避这些端口问题,但是对代码有侵入,也不优雅。还可以修改后端tomcat的proxyPort="xxx",xxx就是nginx的端口解决,这个值不设置就是默认,http对应80,https对应443。
在nginx处,都可以通过设置Host来解决,可以重定向到你想要的任何位置(ip和端口)。
proxy_set_header Host $host:$server_port;
通过proxy_redirect指令也能处理部分情况。
proxy_redirect http://host http://host:81;
nginx使用alias命令进行静态页面转发的时候,如果是.../xxxx1/xxxx2这种会被重定向到.../xxxx1/xxxx2/,nginx运行在8080,防火墙出口是80,重定向的时候就出现问题。它重定向到了nginx的8080端口。
有两种解决方式:
- 如果版本大于等于1.11.8,可以设置absolute_redirect off这样重定向的页面就是相对页面,浏览器自动会加上ip和端口。
- 如果版本小于1.11.8,可以设置port_in_redirect off这样在重定向的时候就没有端口,也即默认端口。
- 两个指令各有用处,看自己的nginx版本选用一种即可。
因为版本用的是1.16.1,可以使用absolute_redirect off;来解决。
但是如果防火墙出口端口不是80,那就最好升级nginx使用absolute_redirect了。注意这种被重定向的页面都会有缓存,所以测试的时候注意清空缓存。
在某些极端的网络环境下,比如防火墙出口端口为80,nginx运行在8080,有一部分人通过外网80访问,有一部分人通过内网8080访问,此时就可以利用nginx的if指令判断$host,指定不同的Host,实现完美的重定向。
为什么proxy反向代理和静态页面处理重定向的问题方法不一致呢?因为反向代理后端是动态服务器,动态服务器在redirect的时候其实是通过拿到Host和Port组装一个地址进行重定向,所以设置好$Host就行;而对于静态页面,没办法动态处理,所以nginx提供了port_in_redirect和absolute_redirect等指令来处理重定向。一点愚见,不知理解是否准确。
另外,nginx是可以通过不同域名但是相同端口运行的,相当于虚拟主机,使用不同的域名访问可以访问到不同的server。
nginx可以非常简单地实现http强制跳转https,目前总结了四种方法:
1. 利用rewrite指令
server {
listen 80;
server_name domain.com;
rewrite ^(.*) https://$server_name$1 permanent;
}
server {
listen 443 ssl;
server_name domain.com;
ssl on;
ssl_certificate /etc/nginx/ssl/domain.com.crt;
ssl_certificate_key /etc/nginx/ssl/domain.com.crt;
# other
}
2. 利用return httpcode指令
server {
listen 80;
server_name domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name domain.com;
....
}
3. 利用error_page指令,只允许HTTP来访问时,用HTTP访问会让Nginx报497错误,然后利用error_page将链接重定向至HTTPS上。使用error_page指令时,将http和https的监听配置写在同一个server块中,对应的其他配置也需要在该server配置块中完成。 需要注意的是,此时需要将error_page
指令语句写在最后,否则不能生效。
server {
listen 80;
listen 443 ssl;
server_name domain.com;
ssl on;
ssl_certificate /etc/nginx/ssl/domain.com.crt;
ssl_certificate_key /etc/nginx/ssl/domain.com.crt;
# other
error_page 497 https://$server_name$request_uri;
}
4. 利用页面meta标签重定向
# index.html
<html>
<meta http-equiv="refresh" content="0;url=https://domain.com/">
</html>
server {
listen 80;
server_name docs.lvrui.io;
location / {
# 将 index.html 文件放到下面的目录下
root /var/www/html/refresh/;
}
}
server {
listen 443 ssl;
server_name domain.com;
index index.html index.htm;
access_log /var/log/nginx/docs.log main;
ssl on;
ssl_certificate /etc/ssl/docs.20150509.cn.crt;
ssl_certificate_key /etc/ssl/docs.20150509.cn.key;
error_page 404 /404.html;
location / {
root /var/www/html/docs;
}
}
nginx的平滑升级:
编译新版本: ./configure(编译参数,可以通过./sbin/nginx -V获取) , make,千万不要make install
备份:cp sbin/nginx sbin/nginxold
升级:make upgrade,此时还未完成升级,./sbin/nginx -V还是原来的nginx版本
make install完成升级
由于nginx可以完成平滑升级,所以nginx的版本一般不要放在带有版本号的目录,以免升级后造成混淆。
{nginx}/sbin/nginx -T 可以dump出来nginx当前加载的配置,这个在误删nginx配置的时候可以起死回生,救人一命。
另外,不管是什么重要的配置,数据库数据,代码等,备份是很重要的!!!