目录
前言
1.重写和重定向的区别是什么?
首先说说关联
那他们的区别呢?
2.“重写”、“重定向”、“隐式转发”、“内部重定向”......这些名词的关系是什么?
3.nginx中return、rewrite、proxy_pass它们的区别是什么?实现的功能是什么?
3.1 return
3.2 rewrite
3.3 proxy_pass
3.4 nginx模块实现重写/重定向总结
4.关于重写/重定向时规则的匹配效率
5.总结
5.1 什么是重写和重定向?
5.2 相关名词是什么对应关系?
5.3 nginx模块实现重写和重定向地对应关系
参考文档
一直对nginx的重写和重定向都是只有一个模糊的认识,只是知道在nginx里return、rewrite、proxy_pass能实现我想要的转发。每次查阅资料时,各种关键词充斥在眼前:“重写”、“重定向”、“隐式转发”、“内部重定向”......一直没有区分清楚他们之前的区别或联系。
随之产生几个问题,想要花点时间搞清楚它们:
首先重写和重定向的最终目的是一样的。假如你通过浏览器和固定的链接经常访问一张“好看的图片”,有一天图片的维护者将它移动了位置(服务器上的目录、移动到其他域名),那意味着你访问不到这张图片了?
为了避免这样的情况给用户带来的困扰,可以使用重写、或者重定向,将你的请求转向新的位置(这张图片新的位置),对你来说还是用老的固定的链接访问到了你喜欢的图片。
重定向:重定向是用户请求服务端后,服务端向客户端发送HTTP 301、302(303、304、307、308),告诉客户端需要去尝试另一个URL。意味着客户端知道使用另一个URL并去访问。(客户端发起两次请求)
重定向的请求路径如下:
重写:重写发生在服务器上。服务器内部将一个URL转到另一个URL,然后返回给客户端。客户端并不知道自己的请求被转过一次,浏览器中的URL也始终是一开始访问的那个。(客户端发起一次请求)
重写的请求路径如下:
粗暴总结:
从浏览器的反馈来看。重写-客户端只会发送一次请求;重定向-客户端会发送两次请求。
重写和重定向在上面已经解释过了。关于其他名词的解释,在网上搜罗了一下:
思来想去,似乎就是对重写和重定向取了好多名字。所以个人理解的总结:
语法:return code [text];
return code URL;
return URL;
默认:—
语境:server, location, if
停止处理请求并返回指定的状态码个客户端。非标准代码444关闭连接而不发送响应头。
语法:rewrite regex replacement [flag];
默认:—
语境:server, location, if
可选[flag]参数:
如果"rewrite ... last;"在location中,且location和rewrite的匹配规则能匹配到相同的URL,则"rewrite ... last;"的flag需要改成break。否则,nginx将进行10次循环匹配,并最终返回500状态码报错。
location /download/ {
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
return 403;
}
如果replacement字符串包含新的请求参数,则修改之前的请求参数会附加在修改后的URI后面。如果不需要参数,则在replacement字符串末尾添加问号,这样修改后的请求不会被附加之前的请求参数。
rewrite ^/users/(.*)$ /show?user=$1? last;
如果正则表达式中包含";"、"}"这种结束符,则整个表达式应该用单引号或双引号引起来。
ngx_http_proxy_module该模块允许将请求传递到另一台服务器。
语法:proxy_pass URL;
默认:—
语境:location, if in location, limit_except
设置代理服务器的协议、地址、端口、可选的URI。
地址——除了IP+端口外,还可以指定域名和upstream。如果指定的是域名,会在配置文件中寻找对应的服务器组(upstream),找不到才会按域名解析来;如果域名解析到多个IP,会以循环的方式使用这些IP。
URI——如果proxy_pass指定了URI,则请求传递到服务器时使用指定的URI替换location部分匹配的URI;如果proxy_pass没有指定URI,则原始请求的URI会传递给服务器。
某些情况下,无法确定请求URI中替换的部分,需要用到正则表达式。可以在location中通过rewrite重写:
location /name/ {
rewrite /name/([^/]+) /users?name=$1 break;
proxy_pass http://127.0.0.1;
}
nginx的模块在实现重写或者重定向时,并不是独立的。不是某个模块只能实现重写,而另一个模块只能实现重定向,并不是这种关系(至少对于rewrite来说不是)。
重定向:
重写:
在重写和重定向时,经常会用到正则表达式来匹配我们想要的URI。但是我们需要注意的时,应该努力保持正则的整洁,越复杂会越影响效率。
下面的示例,通过尽量避免捕获或匹配,从而提高效率:
BAD:
rewrite ^/(.*)$ http://example.com/$1 permanent;
GOOD:
rewrite ^ http://example.com$request_uri? permanent;
BETTER:
return 301 http://example.com$request_uri;
重定向:重定向是用户请求服务端后,服务端向客户端发送HTTP 301、302(303、304、307、308),告诉客户端需要去尝试另一个URL。意味着客户端知道使用另一个URL并去访问。(客户端发起两次请求)
重写:重写发生在服务器上。服务器内部将一个URL转到另一个URL,然后返回给客户端。客户端并不知道自己的请求被转过一次,浏览器中的URL也始终是一开始访问的那个。(客户端发起一次请求)
人理解的总结:
nginx的模块在实现重写或者重定向时,并不是独立的。不是某个模块只能实现重写,而另一个模块只能实现重定向,并不是这种关系(至少对于rewrite来说不是)。
重定向:
重写:
How does "URL Rewrite" differ from "HTTP Redirect"
Module ngx_http_rewrite_module
Module ngx_http_proxy_module
Pitfalls and Common Mistakes | NGINX