相关文章推荐
销魂的海豚  ·  Stream流使用groupingBy+ma ...·  3 年前    · 
慈祥的萝卜  ·  Ansible-playbook ...·  3 年前    · 
讲道义的高山  ·  Spring Cloud实战 | ...·  3 年前    · 

那他们的区别呢?

2.“重写”、“重定向”、“隐式转发”、“内部重定向”......这些名词的关系是什么?

3.nginx中return、rewrite、proxy_pass它们的区别是什么?实现的功能是什么?

3.1 return

3.2 rewrite

3.3 proxy_pass

3.4 nginx模块实现重写/重定向总结

4.关于重写/重定向时规则的匹配效率

5.1 什么是重写和重定向?

5.2 相关名词是什么对应关系?

5.3 nginx模块实现重写和重定向地对应关系

一直对nginx的重写和重定向都是只有一个模糊的认识,只是知道在nginx里return、rewrite、proxy_pass能实现我想要的转发。每次查阅资料时,各种关键词充斥在眼前:“重写”、“重定向”、“隐式转发”、“内部重定向”......一直没有区分清楚他们之前的区别或联系。

随之产生几个问题,想要花点时间搞清楚它们:

  1. 重写和重定向的区别是什么?
  2. nginx中“重写”、“重定向”、“隐式转发”、“内部重定向”......这些名词的关系是什么?在nginx是否都由一个独立的模块、关键字来实现这些的?
  3. nginx中return、rewrite、proxy_pass它们的区别是什么?对于重写和重定向,它们是否各自实现不同的功能?

1.重写和重定向的区别是什么?

首先说说关联

首先重写和重定向的最终目的是一样的。假如你通过浏览器和固定的链接经常访问一张“好看的图片”,有一天图片的维护者将它移动了位置(服务器上的目录、移动到其他域名),那意味着你访问不到这张图片了?

为了避免这样的情况给用户带来的困扰,可以使用重写、或者重定向, 将你的请求转向新的位置 (这张图片新的位置),对你来说还是用老的固定的链接访问到了你喜欢的图片。

那他们的区别呢?

重定向 :重定向是用户请求服务端后,服务端向客户端发送HTTP 301、302(303、304、307、308),告诉客户端需要去尝试另一个URL。意味着客户端知道使用另一个URL并去访问。(客户端发起两次请求)

重定向的请求路径如下:

  1. request1(来自客户端):访问“好看的图片”
  2. response1(来自服务端):你要访问的图片不在这了,你需要去访问“好看的图片新的位置”
  3. request2(来自客户端):访问“好看的图片新的位置”
  4. response2(来自服务端):拿去吧,你要的“好看的图片新的位置”对应的图片

重写 :重写发生在服务器上。服务器内部将一个URL转到另一个URL,然后返回给客户端。客户端并不知道自己的请求被转过一次,浏览器中的URL也始终是一开始访问的那个。(客户端发起一次请求)

重写的请求路径如下:

  1. request1(来自客户端):访问“好看的图片”
  2. 重写(服务端处理):将“好看的图片”改到“好看的图片新的位置”,获取到图片
  3. response1(来自服务端):拿去吧,你要的“好看的图片”对应的图片

粗暴总结 :

从浏览器的反馈来看。重写-客户端只会发送一次请求;重定向-客户端会发送两次请求。

2.“重写”、“重定向”、“隐式转发”、“内部重定向”......这些名词的关系是什么?

重写和重定向在上面已经解释过了。关于其他名词的解释,在网上搜罗了一下:

  • 隐式转发/隐形转发/隐藏式跳转:将请求跳转到另一个网站的页面,并且浏览器中URL保持不变。
  • 显示转发:将请求跳转到另一个网站的页面,浏览器中URL会发生改变。
  • 内部重定向:内部重定向(重写)发生在server端内部,client端不知情,浏览器上URL不会改变。
  • 外部重定向:外部重定向是server端通知client端需要访问新的URL,client端进行第二次访问。浏览器中URL也变成新的URL。

思来想去,似乎就是对重写和重定向取了好多名字。所以个人理解的总结:

  • 重写     = 隐式转发 = 内部重定向
  • 重定向 = 显示转发 = 外部重定向

3.nginx中return、rewrite、proxy_pass它们的区别是什么?实现的功能是什么?

  • return和rewrite都是nginx的ngx_http_rewrite_module模块中的;
  • proxy_pass是nginx的ngx_http_proxy_module模块中的。

3.1 return

语法: return code [text];
return code URL;
return URL;
默认: —
语境: server, location, if

停止处理请求并返回指定的状态码个客户端。非标准代码444关闭连接而不发送响应头。

  • return的状态码为301、302、303、307、308时,则为重定向;
  • return的状态码为其他时,可以返回响应主体[text]。

3.2 rewrite

语法: rewrite regex replacement [flag];
默认: —
语境: server, location, if

  • 如果指定的regex表达式与请求URI匹配,则按照replacement中指定的规则更新URL。
  • rewrite指令会根据配置文件中的顺序依次执行,可以使用[flag]参数终止指令向下继续执行。
  • 如果replacement中替换字符串以“http://”、“https://”、"$scheme"开头,则处理停止,并将 重定向返回给客户端 。

可选[flag]参数:

  • last—— 停止当前处理的ngx_http_rewrite_module指令集,重新开始搜索与修改后的URI匹配的location;(重写)
  • break—— 停止当前处理的ngx_http_rewrite_module指令集;(重写)
  • redirect—— 返回带有302状态码的临时重定向;如果替换字符串不以“http://”、“https://”、"$scheme"开头,则使用;(重定向)
  • permanent—— 返回带有301状态码的永久重定向。(重定向)

如果"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;

如果正则表达式中包含";"、"}"这种结束符,则整个表达式应该用单引号或双引号引起来。

3.3 proxy_pass

ngx_http_proxy_module该模块允许将请求传递到另一台服务器。

语法:proxy_pass URL;
默认:—
语境:location, if in location, limit_except

设置代理服务器的协议、地址、端口、可选的URI。

  • 协议:http、https
  • 地址:域名、IP、upstream
  • 端口:(可选)
  • URI:(可选)
  • 可以使用变量,如:“proxy_pass http://127.0.0.1$request_uri;”
  • 可以代理到Unix套接字路径,如:“proxy_pass http://unix:/tmp/backend.socket:/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; 

3.4 nginx模块实现重写/重定向总结

nginx的模块在实现重写或者重定向时,并不是独立的。不是某个模块只能实现重写,而另一个模块只能实现重定向,并不是这种关系(至少对于rewrite来说不是)。

  • return状态码为301、302、303、304、307、308时,则为重定向
  • rewrite的replacement中替换字符串以“http://”、“https://”、"$scheme"开头,则为重定向
  • rewrite的flag为redirect,则为302重定向
  • rewrite的flag为permanent,则为301重定向
  • rewrite的flag为last时,且replacement中替换字符串不以“http://”、“https://”、"$scheme"开头,则为重写
  • rewrite的flag为break时,且replacement中替换字符串不以“http://”、“https://”、"$scheme"开头,则为重写
  • 使用proxy_pass,则为重写

4.关于重写/重定向时规则的匹配效率

在重写和重定向时,经常会用到正则表达式来匹配我们想要的URI。但是我们需要注意的时,应该努力保持正则的整洁,越复杂会越影响效率。

下面的示例,通过尽量避免捕获或匹配,从而提高效率:

rewrite ^/(.*)$ http://example.com/$1 permanent;

GOOD:

rewrite ^ http://example.com$request_uri? permanent;

BETTER:

return 301 http://example.com$request_uri;

5.1 什么是重写和重定向?

重定向:重定向是用户请求服务端后,服务端向客户端发送HTTP 301、302(303、304、307、308),告诉客户端需要去尝试另一个URL。意味着客户端知道使用另一个URL并去访问。(客户端发起两次请求)

重写:重写发生在服务器上。服务器内部将一个URL转到另一个URL,然后返回给客户端。客户端并不知道自己的请求被转过一次,浏览器中的URL也始终是一开始访问的那个。(客户端发起一次请求)

5.2 相关名词是什么对应关系?

人理解的总结:

  • 重写     = 隐式转发 = 内部重定向
  • 重定向 = 显示转发 = 外部重定向

5.3 nginx模块实现重写和重定向地对应关系

nginx的模块在实现重写或者重定向时,并不是独立的。不是某个模块只能实现重写,而另一个模块只能实现重定向,并不是这种关系(至少对于rewrite来说不是)。

  • return状态码为301、302、303、304、307、308时,则为重定向
  • rewrite的replacement中替换字符串以“http://”、“https://”、"$scheme"开头,则为重定向
  • rewrite的flag为redirect,则为302重定向
  • rewrite的flag为permanent,则为301重定向
  • rewrite的flag为last时,且replacement中替换字符串不以“http://”、“https://”、"$scheme"开头,则为重写
  • rewrite的flag为break时,且replacement中替换字符串不以“http://”、“https://”、"$scheme"开头,则为重写
  • 使用proxy_pass,则为重写

How does "URL Rewrite" differ from "HTTP Redirect"

Module ngx_http_rewrite_module

Module ngx_http_proxy_module

Pitfalls and Common Mistakes | NGINX

Rewrite是Nginx服务器提供的一个重要基本功能,是Web服务器产品中几乎必备的功能。主要的作用是。注意:Nginx服务器的Rewrite功能的实现依赖于PCRE的支持,因此在编译安装Nginx服务器之前,需要安装PCRE库。Nginx使用的是ngx_http_rewrite_module模块来解析和处理Rewrite功能的相关配置。 Rewrite及URL重写,主要是实现地址重写,以及重定向,就是把输入Web的请求重定向到其他URL的过程location 用于匹配 用户访问请求的URL ,来使用哪一个目录中的网页资源,rewrite ....... permanent 修改url 后再次请求访问rewrite /weihu.html 按照修改域名后的 url 直接跳转到对应的 locationrewrite 如果对全URL 重写,则重写部分就以http:// 开头,后面跟上重写后的URL。 例如,请求 http://example.com/admin/test,$uri 是 /admin/test。例如,如果 $uri 是 /admin/test,则 $uri/ 是 /admin/test/。/admin/index.html:回退路径,如果前面的文件或目录都不存在,Nginx 会尝试提供这个路径(相对于 alias 或 root 定义的目录)。如果文件不存在,检查 $uri/ 是否对应一个目录(例如 /usr/nginx/demo/im-admin/test/)。 继续上面的例子,当用户访问 http://aaa.com/index.html 时,源服务器会告诉来访用户,你要的资源在 http://bbb.com/index.html 服务器上,你去找它要吧,此时来访用户根据源服务器的通知,重新到新服务器去获取资源,这就完成了请求的重定向。举例:假设你有一个域名为 aaa.com 网站, 但后面希望改版到 bbb.com 这个域名上,为了尽可能继承原网站的 SEO ,在新域名上线前期,需要将旧域名的流量全部汇聚到新域名的站点上来,此时就需要用到重定向功能了。..... rewrite功能: 使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。比如: 更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用, 例如a=1&b=2 只对/abc/bbs/index.php重写。 (1)重写url,可以重写path,也可以重写整个url(存在协议,默认返回302,代表临时跳转)。 (2)4 个 flag:last、break、redirect、permanent。存在 flag 时,在当前location 中,不再执行之后的 rewrite指令集(包括 rewrite、return)中的指令;break 和 last 正好相反,break 中止对其它location 的规则匹配,last 继续向其它 location 进行规则匹配; 2、使用举例... 重定向指的是当用户访问某个URL时,服务器将该URL重定向到另外一个URL的过程。重定向可以帮助我们更好的管理网站内容,优化SEO效果,提升用户体验等。Nginx中提供了多种重定向方式,包括301重定向、302重定向、rewrite重定向等。 rewrite就是把当前访问的页面跳转到其他页面正向代理我们是知道代理服务器的地址,也知道我们访问的web服务器反向代理,客户端还是访问的代理地址,但是具体的访问web服务器是哪一台,我们并不知道。