302是HTTP协议中的一个经常被使用状态码,是多种重定向方式的一种,其语义经常被解释为“Moved Temporarily”。这里顺带提一下,现实中用到的302多为误用(与303,307混用),在HTTP/1.1中,它的语义为“Found”. 302有时候很明显,有时候又比较隐蔽。最简单
302是HTTP协议中的一个经常被使用状态码,是多种重定向方式的一种,其语义经常被解释为“Moved Temporarily”。这里顺带提一下,现实中用到的302多为误用(与303,307混用),在HTTP/1.1中,它的语义为“Found”.
302有时候很明显,有时候又比较隐蔽。最简单的情况,是当我们在浏览器中输入一个网址A,然后浏览器地址栏会自动跳到B,进而打开一个网页,这种情况就很可能是302。
比较隐蔽的情况经常发生在嵌入到网页的播放器中。例如,当你打开一个优酷视频播放页面时,抓包观察一下就会经常发现302的影子。但由于这些url并不是直接在浏览器中打开的,所以在浏览器的地址栏看不到变化,当然,如果将这些具体的url特意挑出来复制到浏览器地址栏里,还是可以观察到的。
上一段提到了优酷。其实现在多数在线视频网站都会用到302,原因很简单,视频网站流量一般较大,都会用到CDN,区别只在于是用自建CDN还是商业CDN。而由于302的重定向语义(再重复一遍,302的语义广泛的被误用,在使用302的时候,我们很可能应该使用303或307,但后面都不再纠结这一点),可以与CDN中的调度很好的结合起来。
我们来看一个例子,打开一个网易视频播放页面,抓一下包,找到302状态的那个url。例如:
<code>http://flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 </code>
我们把它复制到浏览器地址栏中,会发现地址栏迅速的变为了另外一个url,这个Url是不定的,有可能为:
<code>http://14.18.140.83/f6c00af500000000-1408987545-236096587/data6/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 </code>
用curl工具会更清楚的看到整个过程:
<code>curl -I "http://flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4" -L HTTP/1.1 302 Moved Temporarily Server: nginx Date: Mon, 25 Aug 2014 14:49:43 GMT Content-Type: text/html Content-Length: 154 Connection: keep-alive NG: CCN-SW-1-5L2 X-Mod-Name: GSLB/3.1.0 Location: http://119.134.254.9/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 HTTP/1.1 302 Moved Temporarily Server: nginx Date: Mon, 25 Aug 2014 14:49:41 GMT Content-Type: text/html Content-Length: 154 Connection: keep-alive X-Mod-Name: Mvod-Server/4.3.3 Location: http://119.134.254.7/cc89fdac00000000-1408983581-2095617481/data4/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 NG: CHN-SW-1-3Y1 HTTP/1.1 200 OK Server: nginx Date: Mon, 25 Aug 2014 14:49:41 GMT Content-Type: video/mp4 Content-Length: 3706468 Last-Modified: Mon, 25 Aug 2014 00:23:50 GMT Connection: keep-alive Cache-Control: no-cache ETag: "53fa8216-388e64" NG: CHN-SW-1-3g6 X-Mod-Name: Mvod-Server/4.3.3 Accept-Ranges: bytes </code>
可以看到,这中间经历了两次302。
先暂时将这个例子放在一边,再来说说另一个重要的术语:proxy.我们通常会戏称,某些领导是302类型的,某些领导是proxy类型的。302类型的领导,一件事情经过他的手,会迅速的转给他人,而proxy类型的领导则会参与到事情中来,甚至把事情全部做完。
回到上面的例子,如果访问一个url中途会有多个302,那如果需要用Nginx设计一个proxy,来隐藏掉中间所有的这些302,该怎么做呢?
1.原始Proxy
我们知道,Nginx本身就是一个优秀的代理服务器。因此,首先我们来架设一个Nginx正向代理,服务器IP为192.168.109.128(我的一个测试虚拟机)。
初始配置简化如下:
<code>server { listen 80; location / { rewrite_by_lua ' ngx.exec("/proxy-to" .. ngx.var.request_uri) '; } location ~ /proxy-to/([^/]+)(.*) { proxy_pass http://$1$2$is_args$query_string; } } </code>
实现的功能是,当使用
<code>http://192.168.109.128/xxxxxx </code>
访问该代理时,会proxy到xxxxxx所代表的真实服务器。
测试结果如下:
<code>curl -I "http://192.168.109.128/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4" -L HTTP/1.1 302 Moved Temporarily Server: nginx/1.4.6 Date: Mon, 25 Aug 2014 14:50:54 GMT Content-Type: text/html Content-Length: 154 Connection: keep-alive NG: CCN-SW-1-5L2 X-Mod-Name: GSLB/3.1.0 Location: http://183.61.140.24/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 HTTP/1.1 302 Moved Temporarily Server: nginx Date: Mon, 25 Aug 2014 14:50:55 GMT Content-Type: text/html Content-Length: 154 Connection: keep-alive X-Mod-Name: Mvod-Server/4.3.3 Location: http://183.61.140.20/540966e500000000-1408983655-236096587/data1/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 NG: CHN-ZJ-4-3M4 HTTP/1.1 200 OK Server: nginx Date: Mon, 25 Aug 2014 14:50:55 GMT Content-Type: video/mp4 Content-Length: 3706468 Last-Modified: Mon, 25 Aug 2014 00:31:03 GMT Connection: keep-alive Cache-Control: no-cache ETag: "53fa83c7-388e64" NG: CHN-ZJ-4-3M4 X-Mod-Name: Mvod-Server/4.3.3 Accept-Ranges: bytes </code>
可见,虽然使用proxy,但过程与原始访问没有什么区别。访问过程为,当访问
<code>http://192.168.109.128/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 </code>
时,Nginx会将该请求proxy到
<code>http://flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 </code>
而后者马上就会返回一个302,所以Nginx作为proxy,将该302传回到客户端,客户端重新发起请求,进而重复之前的多次302.这里说明一个问题,一旦Nginx的proxy的后端返回302后,客户端即与Nginx这个proxy脱离关系了,Nginx无法起到完整的代理的作用。
2. 第1次修改
将配置文件修改为:
<code>server { listen 80; location / { rewrite_by_lua ' ngx.exec("/proxy-to" .. ngx.var.request_uri) '; } location ~ /proxy-to/([^/]+)(.*) { proxy_pass http://$1$2$is_args$query_string; error_page 302 = @error_page_302; } location @error_page_302 { rewrite_by_lua ' local _, _, upstream_http_location = string.find(ngx.var.upstream_http_location, "^http:/(.*)$") ngx.header["zzzz"] = "/proxy-to" .. upstream_http_location ngx.exec("/proxy-to" .. upstream_http_location); '; } } </code>
与上面的区别在于,使用了一个error_page,目的是当发现proxy的后端返回302时,则用这个302的目的location继续proxy,而不是直接返回给客户端。并且这个逻辑里面包含着递归的意思,一路跟踪302,直到最终返回200的那个地址。测试结果如下:
<code>curl -I "http://192.168.109.128/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4" -L HTTP/1.1 302 Moved Temporarily Server: nginx/1.4.6 Date: Mon, 25 Aug 2014 15:01:17 GMT Content-Type: text/html Content-Length: 154 Connection: keep-alive NG: CCN-SW-1-5L2 X-Mod-Name: GSLB/3.1.0 Location: http://183.61.140.24/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 HTTP/1.1 302 Moved Temporarily Server: nginx Date: Mon, 25 Aug 2014 15:01:17 GMT Content-Type: text/html Content-Length: 154 Connection: keep-alive X-Mod-Name: Mvod-Server/4.3.3 Location: http://183.61.140.20/a90a952900000000-1408984277-236096587/data1/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 NG: CHN-ZJ-4-3M4 HTTP/1.1 200 OK Server: nginx Date: Mon, 25 Aug 2014 15:01:17 GMT Content-Type: video/mp4 Content-Length: 3706468 Last-Modified: Mon, 25 Aug 2014 00:31:03 GMT Connection: keep-alive Cache-Control: no-cache ETag: "53fa83c7-388e64" NG: CHN-ZJ-4-3M4 X-Mod-Name: Mvod-Server/4.3.3 Accept-Ranges: bytes </code>
可见,本次修改仍然没有成功!
为什么呢?分析一下,我们在@error_page_302这个location里已经加了一个头部打印语句,可是在测试中,该头部并没有打出来,可见流程并没有进入到@error_page_302这个location。
原因在于
<code>error_page 302 = @error_page_302; </code>
error_page默认是本次处理的返回码。作为proxy,本次处理,只要转发上游服务器的响应成功,应该状态码都是200.即,我们真正需要检查的,是proxy的后端服务器返回的状态码,而不是proxy本身返回的状态码。查一下Nginx的wiki,proxy_intercept_errors指令正是干这个的:
<code>Syntax: proxy_intercept_errors on | off; Default: proxy_intercept_errors off; Context: http, server, location Determines whether proxied responses with codes greater than or equal to 300 should be passed to a client or be redirected to nginx for processing with the error_page directive. </code>
3. 第二次修改
<code>server { listen 80; proxy_intercept_errors on; location / { rewrite_by_lua ' ngx.exec("/proxy-to" .. ngx.var.request_uri) '; } location ~ /proxy-to/([^/]+)(.*) { proxy_pass http://$1$2$is_args$query_string; error_page 302 = @error_page_302; } location @error_page_302 { rewrite_by_lua ' local _, _, upstream_http_location = string.find(ngx.var.upstream_http_location, "^http:/(.*)$") ngx.header["zzzz"] = "/proxy-to" .. upstream_http_location ngx.exec("/proxy-to" .. upstream_http_location); '; } } </code>
与上一次修改相比,区别仅仅在于增加了一个proxy_intercept_errors指令。测试结果如下:
<code>curl -I "http://192.168.109.128/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4" -L HTTP/1.1 302 Moved Temporarily Server: nginx/1.4.6 Date: Mon, 25 Aug 2014 15:05:54 GMT Content-Type: text/html Content-Length: 160 Connection: keep-alive zzzz: /proxy-to/183.61.140.24/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 </code>
这次更神奇了,直接返回一个302状态完事,也不继续跳转了。
问题出在,虽然第一次302,请求成功的进入到@error_page_302,但后续的error_page指令却没起作用。也就是说,error_page只检查了第一次后端返回的状态码,而没有继续检查后续的后端状态码。
查一下资料,这个时候,另一个指令 recursive_error_pages就派上用场了。
4. 第3次修改
<code>server { listen 80; proxy_intercept_errors on; recursive_error_pages on; location / { rewrite_by_lua ' ngx.exec("/proxy-to" .. ngx.var.request_uri) '; } location ~ /proxy-to/([^/]+)(.*) { proxy_pass http://$1$2$is_args$query_string; error_page 302 = @error_page_302; } location @error_page_302 { rewrite_by_lua ' local _, _, upstream_http_location = string.find(ngx.var.upstream_http_location, "^http:/(.*)$") ngx.header["zzzz"] = "/proxy-to" .. upstream_http_location ngx.exec("/proxy-to" .. upstream_http_location); '; } } </code>
与上一次相比,仅仅增加了recursive_error_pages on这条指令。测试结果如下:
<code>curl -I "http://192.168.109.128/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4" -L HTTP/1.1 200 OK Server: nginx/1.4.6 Date: Mon, 25 Aug 2014 15:09:04 GMT Content-Type: video/mp4 Content-Length: 3706468 Connection: keep-alive zzzz: /proxy-to/14.18.140.83/f48bad0100000000-1408984745-236096587/data6/flv.bn.netease.com/tvmrepo/2014/8/5/P/EA3I1J05P/SD/EA3I1J05P-mobile.mp4 Last-Modified: Mon, 25 Aug 2014 00:21:07 GMT Cache-Control: no-cache ETag: "53fa8173-388e64" NG: CHN-MM-4-3FE X-Mod-Name: Mvod-Server/4.3.3 Accept-Ranges: bytes </code>
可见,Nginx终于成功的返回200了。此时,Nginx才真正起到了一个Proxy的功能,隐藏了一个请求原本的多个302链路,只返回客户端一个最终结果。
5. 小结
综上,通过proxy_pass、error_page、proxy_intercept_errors、recursive_error_pages这几个指令的配合使用,可以向客户端隐藏一条请求的跳转细节,直接返回用户一个状态码为200的最终结果。
奇怪的是,在Nginx的官方wiki中并没有recursive_error_pages指令的相关说明。
本文出自:http://pureage.info/, 原文地址:http://pureage.info/2014/08/25/hiding-302-using-proxy-pass.html, 感谢原作者分享。

NginxProxyManager配置解析与优化概述:NginxProxyManager是一个基于Nginx的反向代理管理工具,可以帮助我们方便地配置和管理反向代理服务器。在使用NginxProxyManager的过程中,我们可以通过对其配置进行解析与优化,提高服务器的性能与安全性。配置解析:配置文件位置和结构:NginxProxyManag

proxyprotocol在nginx中应用我们知道nginx是一个web服务器和代理服务器,它一般工作在proxyserver或者负载均衡软件(Haproxy,AmazonElasticLoadBalancer(ELB)的后面。客户端首先请求proxyserver或者LSB负载均衡软件,然后再到nginx进行真实的web访问。因为经过了多层软件,所以客户端的一些信息比如ip地址,端口号等可能就会被隐藏,这对于我们问题分析,数据统计都是不利的。因为对于nginx来说,我们希望能够获得真实的客户端

NginxProxyManager下的容器与微服务的部署策略,需要具体代码示例摘要:随着微服务架构的流行,容器化技术成为了现代软件开发的重要组成部分。而在微服务架构中,NginxProxyManager扮演着很重要的角色,用于管理和代理微服务的流量。本文将介绍如何使用NginxProxyManager来部署和管理容器化的微服务,并提供相关的代码示

NginxProxyManager教程:快速入门指南,需要具体代码示例引言:随着网络技术的发展,代理服务器成为我们日常使用互联网的一部分。NginxProxyManager是一个基于Nginx的代理服务器管理平台,可以帮助我们快速建立和管理代理服务器。本篇文章将为大家介绍NginxProxyManager的快速入门指南,以及一些具体的代码示例。一

如何使用NginxProxyManager实现多台服务器的负载均衡NginxProxyManager是一个基于Nginx开发的代理服务器管理工具,它提供了一个简单易用的Web界面,可以方便地配置和管理Nginx代理服务器。在实际应用中,我们经常需要将请求分发到多台服务器上,以实现负载均衡和提高系统的性能和可用性。本文将介绍如何使用NginxProx

如何使用NginxProxyManager实现快速缓存HTML页面引言:在现代网络应用中,快速加载网页是一个重要的需求。为了提高用户体验,我们可以使用NginxProxyManager来实现快速缓存HTML页面。本文将向您展示如何使用NginxProxyManager来实现这一目标,并提供具体的代码示例。第一部分:安装与配置NginxProxy

NginxProxyManager原理与实践:优化网站性能的关键,需要具体代码示例引言:在当今互联网时代,网站性能对于用户体验和搜索引擎优化至关重要。为了提高网站的性能,一个有效的方法是使用Nginx作为反向代理服务器来管理和分发流量。本文将介绍NginxProxyManager的原理与实践,展示如何通过NginxProxyManager优化网站

NginxProxyManager是一个用于管理Nginx代理服务器的工具,通过使用它可以实现HTTP请求的缓存加速。下面将详细介绍如何使用NginxProxyManager实现缓存加速,并提供具体的代码示例。一、安装和配置NginxProxyManager安装NginxProxyManager:$npminstall-g@nginx


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

MantisBT
Mantis ialah alat pengesan kecacatan berasaskan web yang mudah digunakan yang direka untuk membantu dalam pengesanan kecacatan produk. Ia memerlukan PHP, MySQL dan pelayan web. Lihat perkhidmatan demo dan pengehosan kami.

PhpStorm versi Mac
Alat pembangunan bersepadu PHP profesional terkini (2018.2.1).

VSCode Windows 64-bit Muat Turun
Editor IDE percuma dan berkuasa yang dilancarkan oleh Microsoft

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

Muat turun versi mac editor Atom
Editor sumber terbuka yang paling popular
