Nginx는 청크 된 컨텐츠의 Content-Length 헤더를 제거합니다


10

스크립트를 프록시하기 위해 nginx 1.2.3을 사용합니다.

proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8880;
proxy_buffering off;
proxy_read_timeout 300s;
gzip off;

스크립트는 모두 전송 Transfer-encoding: chunkedContent-Length: 251:

HTTP/1.0 307 Temporary Redirect
Content-length: 251
Pragma: no-cache
Location: /...
Cache-control: no-cache
Transfer-encoding: chunked

둘 다 필요하지만 nginx는 자동으로 다음을 제거합니다 Content-Length.

HTTP/1.1 302 Found
Server: nginx/1.2.3
Content-Type: application/json; charset=utf-8
Content-Length: 58
Connection: keep-alive
Location: /...

결과적으로 클라이언트는 청크가 전송되기를 기다리지 않습니다. 이전 버전의 nginx에서 작동했습니다.


nginx 프록시에서 헤더는 어떻게 생겼습니까?
hrunting

어떤 버전으로 작업 했습니까?
cnst

이전에는 nginx 0.9.8에서 작업했습니다.
Julien

HTTP 프로토콜을 위반하고 있습니다. 1.1.4 버전까지는 청크 인코딩을 전혀 지원하지 않기 때문에 nginx 0.9.8에서 작동합니다.
VBart

답변:


11

불행히도 cnst의 게시물에 대해서는 언급 할 수 없으므로 여기에 대답 할 것입니다.

nginx_http_proxyHTTP / 1.0 업스트림 기본적 회담으로 모듈. 지시문으로 변경할 수 있습니다 proxy_http_version 1.1.

307버전에는 청크 분할 코딩 및 상태 코드 가 없지만 스크립트가 HTTP / 1.0 응답을 반환하는 원인 일 수도 있습니다 .

실제로는 의미가 없으므로 리디렉션 과 함께 청크 코딩을 사용해서는 안됩니다 .

또한 nginx 는 청크 를 업스트림에서 클라이언트로 하나씩 전달하지 않는 것처럼 보이지만 업스트림의 응답을 버퍼링합니다 . Content-Length는 정의에 있기 때문에 헤더 필드는 무시됩니다. 이 모든 것이 문서화되지 않은 것처럼 보이기 때문에 모듈 의 소스 코드 를 살펴 봐야했습니다 .

nginx_tcp_proxy_module청크 된 콘텐츠를 원시 TCP 데이터로 프록시하는 방법 을 시도해 볼 수 있습니다 . Github의 모듈


UPDATE (10.04.14) 모듈 지원 갖는 헤더 하나 (이 중, ) 컨트롤 응답 버퍼링 여부를해야하는지 여부.
nginx_http_proxyX-Accel-* X-Accel-Buffering: yes|no

이 헤더 ( X-Accel-Buffering: no)를 백엔드의 응답에 추가하면 nginx가 청크를 클라이언트에 직접 전달합니다.

이 헤더를 사용하면 요청별로 버퍼링을 제어 할 수 있습니다 .

이 모듈에는 응답 버퍼링을 활성화 또는 비활성화하기 위한 구성 지시문 도 있습니다 proxy_buffering(버퍼링이 아니라는 것은 덩어리 전송이 작동 함을 의미합니다).

프록시 버퍼링 (헤더 및 지시문 기반)은 여기 에 문서화되어 있습니다 .


그는 그것으로도 그렇게해서는 안됩니다 nginx_tcp_proxy_module. 일부 브라우저에서는 오류 허용 성이 매우 뛰어나므로 일부 브라우저에서만 작동합니다.
VBart

이 모든 것이 문서화되지 않은 것 같습니다 . RFC 2616에 문서화되어 있습니다. 13.5.1을 참조하십시오 .
VBart

@VBart 물론 표준이 있지만 nginx 가 표준을 구현 하는 방법에 대한 정보는 거의 없습니다 . TCP 프록시 모듈은 제안 된 해결 방법 입니다.
루카스

9

Lukas가 암시하는 것처럼 HTTP 1.1 Content-LengthTransfer-Encoding세트 가 있으면 금지 합니다 .

인용 http://www.ietf.org/rfc/rfc2616.txt :

   3.If a Content-Length header field (section 14.13) is present, its
     decimal value in OCTETs represents both the entity-length and the
     transfer-length. The Content-Length header field MUST NOT be sent
     if these two lengths are different (i.e., if a Transfer-Encoding
     header field is present). If a message is received with both a
     Transfer-Encoding header field and a Content-Length header field,
     the latter MUST be ignored.

또한 HTTP 1.1을 준수하는 Nginx의 올바른 동작은 HTTP 요청 밀수 공격 을 막는 데 큰 도움이됩니다 .
amn

3

특히 리디렉션 응답을 사용하여 스크립트에 청크 인코딩이 필요한 이유를 구체적으로 설명하지 않았습니다.

나는 여기서 많은 문제를 봅니다.

  • Transfer-Encoding: chunked입니다 HTTP/1.1기능은 (그리고 스크립트가 함께 회신 것으로 보인다 HTTP/1.0헤더)

  • 전혀 없다 307인은HTTP/1.0

  • 의 전체 목적은 chunked당신이 모르는 것이 무엇인지 당신 Content-Length했을 것이다, 그래서 chunked내 길이 제공하는 대신에 사용되는 Content-Length실제 내용과 혼합 길이가 응답의 신체 내에서 제공되는 대신을,,, 스크립트가 두 헤더를 먼저 생성하는 것은 의미가 없습니다.

나는 개인적으로 익숙하지 chunked않지만 http://en.wikipedia.org/wiki/Chunked_transfer_encodinghttp://tools.ietf.org/html/rfc2616#section-3.6.1 의 기본 정보에 따르면, 청크 분할 인코딩에 대한 스크립트의 전체 처리가 완전히 잘못되었을 수 있습니다.

위의 내용이 여전히 다루어지지 않는다면, 실제로는 그렇지 않다면, 307또는 " 302http"상태 코드가 포함 된 회신 에 "이상한"인코딩이 제공되어야 하는 이유도 불분명 합니다. 최근 nginx 메일 링리스트에서 비슷한 토론이 있었으며 410 Gone다른 오류 페이지는 항상 gzip압축에서 제외되었으며 , 여기서도 같은 감정이 적용됩니다. ( http://mailman.nginx.org/pipermail/nginx/2013-March/037890.html )


나는 사용자가 기다리게하기 위해 그것을 사용한다 : 나는 매초마다 청크를 보내서, 사용자는 타임 아웃없이 X 초 동안 리디렉션을 기다릴 것이다
Julien

나는 (이런 일이 / 1.0 HTTP / 1.1 첫번째 수정 HTTP에 조언을 줄 변화를)하고 청크 인코딩이 잘못되지 않았는지 확인합니다. 최신 버전의 nginx는 아마도 헤더가 잘못되어 의존하는 일부 헤더를 버릴 것입니다.
cnst

1

html5 비디오 태그를 통해 mp4 파일을 스트리밍하는 것과 동일한 문제가있었습니다.

Chrome이 특정 시점에서 ERR_CONTENT_LENGTH_MISMATCH를 트리거하는 동안 Safari와 Firefox가 정상적으로 작동했습니다 (그러나 실패하기 전에 몇 분 동안 비디오를 처리 할 수있었습니다).

mp4 파일에 대한 캐시 제어를 끈 후에도 문제가 재현되지 않았습니다.


0

도움이되는 경우를 대비하여 SO에 게시 한이 답변을 공유하십시오 : https : //.com

청크가 제공되지 않아 mp4 재생과 비슷한 문제가 발생했으며 Apple 가이드에 따라 아래 나열된 문제를 확인했습니다. 나는 전체 파일을 다운로드하고 아래 수정 후 첫 번째 청크 만 다운로드하고 있음을 확인했습니다.

curl --range 0-99 http://example.com/test.mov -o /dev/null

nginx.conf에서 gzip 압축 설정을 변경하여 Safari .mp4 재생을 해결하여 .mp4 파일의 gzip 압축을 제거했습니다 .

다음은 참조를 위해 nginx의 블록입니다. (참고 : 앱 구성 방법에 따라 위치 줄을 다음과 같이 변경해야 할 수도 있습니다.location ~ \.mp4$ {

location ~ ^/(assets|system|videos)/  {
   expires max;
   add_header Cache-Control public;
   add_header ETag "";
   gzip on;
   gzip_http_version 1.1;
   gzip_vary on;
   gzip_comp_level 6;
   gzip_proxied any;

   # Reference configuration
   #gzip_types text/plain text/html text/css application/json application/javascript application/x-javascript text/javascript video/mp4 application/mp4 image/jpeg image/png image/svg+xml application/x-font-ttf application/x-font-truetype application/font-woff application/font-woff2 application/vnd.ms-fontobject;

   # Kelton trying to fix cloudflare by removing the mp4 settings
   gzip_types text/plain text/html text/css application/json application/javascript application/x-javascript text/javascript image/jpeg image/png image/svg+xml application/application/x-font-ttf application/x-font-truetype application/font-woff application/font-woff2 application/vnd.ms-fontobject;
}

Apple 설명서 참조 링크 : https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html#//apple_ref/doc/uid/TP40006514-SW6

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.