목차
1.原始Proxy
4. 第3次修改
3. 第二次修改
5. 小结
데이터 베이스 MySQL 튜토리얼 用proxy_intercept_errors和recursive_error_pages代理多次3

用proxy_intercept_errors和recursive_error_pages代理多次3

Jun 07, 2016 pm 04:38 PM
errors proxy

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指令的相关说明。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Nginx Proxy Manager 구성 분석 및 최적화 Nginx Proxy Manager 구성 분석 및 최적화 Sep 26, 2023 am 09:24 AM

NginxProxyManager 구성 분석 및 최적화 개요: NginxProxyManager는 Nginx 기반의 역방향 프록시 관리 도구로 역방향 프록시 서버를 쉽게 구성하고 관리하는 데 도움이 됩니다. NginxProxyManager를 사용하는 과정에서 서버 구성을 분석하고 최적화하여 서버의 성능과 보안을 향상시킬 수 있습니다. 구성 분석: 구성 파일 위치 및 구조: NginxProxyManag

nginx에서 프록시 프로토콜을 구성하고 사용하는 방법 nginx에서 프록시 프로토콜을 구성하고 사용하는 방법 May 18, 2023 am 08:47 AM

nginx에서 프록시 프로토콜을 사용하는 경우 nginx는 웹 서버이자 프록시 서버라는 것을 알고 있습니다. 일반적으로 클라이언트는 프록시 서버 또는 로드 밸런싱 소프트웨어(Haproxy, Amazon Elastic LoadBalancer(ELB)) 뒤에서 작동합니다. 그런 다음 nginx로 실제 웹 액세스를 수행합니다. 여러 계층의 소프트웨어를 거쳤기 때문에 IP 주소, 포트 번호 등과 같은 일부 클라이언트 정보가 숨겨질 수 있으며 이는 nginx의 경우 문제 분석 및 데이터 통계에 해로울 수 있습니다. , 우리는 실제 고객을 확보하고 싶습니다

Nginx 프록시 관리자 튜토리얼: 빠른 시작 가이드 Nginx 프록시 관리자 튜토리얼: 빠른 시작 가이드 Sep 27, 2023 pm 05:39 PM

NginxProxyManager 튜토리얼: 빠른 시작 가이드, 필요한 특정 코드 예제 소개: 네트워크 기술의 발전으로 프록시 서버는 일상적인 인터넷 사용의 일부가 되었습니다. NginxProxyManager는 Nginx 기반의 프록시 서버 관리 플랫폼으로, 프록시 서버를 신속하게 구축하고 관리하는 데 도움이 됩니다. 이 기사에서는 NginxProxyManager의 빠른 시작 가이드와 일부 특정 코드 예제를 소개합니다. 하나

Nginx Proxy Manager에서의 컨테이너 및 마이크로서비스 배포 전략 Nginx Proxy Manager에서의 컨테이너 및 마이크로서비스 배포 전략 Sep 27, 2023 pm 01:06 PM

NginxProxyManager에서 컨테이너 및 마이크로서비스의 배포 전략에는 특정 코드 예제가 필요합니다. 요약: 마이크로서비스 아키텍처의 인기로 인해 컨테이너화 기술은 현대 소프트웨어 개발의 중요한 부분이 되었습니다. 마이크로서비스 아키텍처에서 NginxProxyManager는 마이크로서비스의 트래픽을 관리하고 프록시하는 데 사용되는 매우 중요한 역할을 합니다. 이 문서에서는 NginxProxyManager를 사용하여 컨테이너화된 마이크로서비스를 배포 및 관리하는 방법을 소개하고 관련 코드 예제를 제공합니다.

Nginx 프록시 관리자를 사용하여 여러 서버의 로드 밸런싱을 달성하는 방법 Nginx 프록시 관리자를 사용하여 여러 서버의 로드 밸런싱을 달성하는 방법 Sep 27, 2023 pm 09:42 PM

NginxProxyManager를 사용하여 여러 서버의 로드 밸런싱을 달성하는 방법 NginxProxyManager는 Nginx를 기반으로 개발된 프록시 서버 관리 도구로 Nginx 프록시 서버를 쉽게 구성하고 관리할 수 있는 간단하고 사용하기 쉬운 웹 인터페이스를 제공합니다. 실제 애플리케이션에서는 로드 밸런싱을 달성하고 시스템 성능과 가용성을 향상시키기 위해 요청을 여러 서버에 분산해야 하는 경우가 많습니다. 이 기사에서는 NginxProx를 사용하는 방법을 소개합니다.

Nginx 프록시 관리자는 HTTP 요청의 캐시 가속을 구현합니다. Nginx 프록시 관리자는 HTTP 요청의 캐시 가속을 구현합니다. Sep 26, 2023 am 10:53 AM

NginxProxyManager는 Nginx 프록시 서버를 관리하기 위한 도구입니다. 이를 사용하면 HTTP 요청의 캐시 가속을 달성할 수 있습니다. 다음에서는 NginxProxyManager를 사용하여 캐시 가속을 구현하는 방법을 자세히 소개하고 구체적인 코드 예제를 제공합니다. 1. NginxProxyManager 설치 및 구성 NginxProxyManager 설치: $npminstall-g@nginx

Nginx Proxy Manager의 로그 분석 및 모니터링 Nginx Proxy Manager의 로그 분석 및 모니터링 Sep 26, 2023 am 09:21 AM

NginxProxyManager의 로그 분석 및 모니터링에는 특정 코드 예제가 필요합니다. 소개: NginxProxyManager는 Nginx를 기반으로 하는 프록시 서버 관리 도구로, 프록시 서버를 관리하고 모니터링하는 간단하고 효과적인 방법을 제공합니다. 실제 작업에서는 잠재적인 문제를 발견하거나 적시에 성능을 최적화하기 위해 NginxProxyManager의 로그를 분석하고 모니터링해야 하는 경우가 많습니다. 이 기사에서는 일반적으로 사용되는 몇 가지 사용 방법을 소개합니다.

Nginx 프록시 관리자 원칙 및 실습: 웹사이트 성능 최적화의 핵심 Nginx 프록시 관리자 원칙 및 실습: 웹사이트 성능 최적화의 핵심 Sep 26, 2023 am 11:06 AM

NginxProxyManager 원리 및 실습: 웹사이트 성능 최적화의 핵심은 특정 코드 예제가 필요합니다. 소개: 오늘날 인터넷 시대에 웹사이트 성능은 사용자 경험과 검색 엔진 최적화에 매우 중요합니다. 웹사이트의 성능을 향상시키기 위한 효과적인 방법은 Nginx를 역방향 프록시 서버로 사용하여 트래픽을 관리하고 분산시키는 것입니다. 이 기사에서는 NginxProxyManager의 원칙과 사례를 소개하고 NginxProxyManager를 통해 웹사이트를 최적화하는 방법을 보여줍니다.

See all articles