Nginx, yığınlanmış içerik için İçerik Uzunluğu üstbilgisini kaldırır


11

Ben bir komut dosyası proxy için nginx 1.2.3 kullanın:

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

Komut hem gönderir Transfer-encoding: chunkedve Content-Length: 251:

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

Her ikisine de ihtiyacım var, ancak nginx otomatik olarak kaldırır 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: /...

Sonuç olarak, istemciler parçaların gönderilmesini beklemezler. Bu, önceki bir nginx sürümü ile çalışırdı.


Üstbilgiler nginx proxy'sinden nasıl görünüyor?
Şubat'ta

hangi versiyonla çalışırdı?
cnst

Eskiden nginx 0.9.8
Julien

HTTP protokolünü ihlal ediyorsunuz. 1.1.4 sürümüne kadar yığın kodlamayı desteklemediğinden, nginx 0.9.8 ile çalışır.
VBart

Yanıtlar:


11

Ne yazık ki, cnst'ın gönderisi hakkında yorum yapamam - bu yüzden burada cevap vereceğim.

nginx_http_proxyHTTP / 1.0 üst akışında varsayılan görüşmelerin tarafından modülü. Bu direktif ile değiştirilebilir proxy_http_version 1.1.

Bu 307sürümde yığın kodlama ve durum kodu olmasa da, betiğinizin HTTP / 1.0 yanıtı döndürmesine neden olabilir .

Gerçekten bir anlam ifade etmediği için, bir yönlendirme ile yığınlanmış kodlama kullanmamalısınız .

Ek olarak , nginx , yığınları istemciye birer birer iletmez , ancak yukarı akışın yanıtını arabelleğe alır . Content-LengthO tanım aykırıdır çünkü başlık alanı göz ardı edilir. Tüm bunların belgesiz olduğu için modülün kaynak koduna bakmak zorunda kaldım .

nginx_tcp_proxy_moduleParçalanan içeriği ham TCP verisi olarak proxy yapmak için deneyebilirsiniz : Github'daki Modül


UPDATE (10.04.14) modül desteği vardır başlıkları on (ki, ) kontrol yanıtı tamponlu ya da gerekip gerekmediğini.
nginx_http_proxyX-Accel-* X-Accel-Buffering: yes|no

Bu üstbilginin ( X-Accel-Buffering: no) arka ucun yanıtına eklenmesi , nginx'in doğrudan istemciye parçaları iletmesine neden olur.

Bu başlık, arabelleğe almayı isteğe bağlı olarak kontrol etmeyi sağlar .

Modül ayrıca yanıt arabelleğe almayı etkinleştirmek veya devre dışı bırakmak için bir yapılandırma yönergesine sahiptir proxy_buffering(arabelleğe alma değil, gönderilerin gönderileceği anlamına gelir).

Proxy arabelleğe alma (hem başlık hem de yönerge tabanlı) burada belgelenmiştir .


Bunu bile yapmamalı nginx_tcp_proxy_module. Bazı tarayıcılarla çalışır, çünkü çok hataya dayanıklıdırlar.
VBart

çünkü bunların hepsi belgelenmemiş gibi görünüyor . RFC 2616'da belgelenmiştir. Bkz. 13.5.1 .
VBart

@VBart Tabii standartlar var - ama hakkında sadece çok az bilgi var ne kadar özellikle nginx uygular işler.Gerekli TCP vekil modülü önerilen bir hust olan geçici çözüm .
Lukas

9

Lukas alludet olarak HTTP 1.1 Content-Lengthbir Transfer-Encodingdizi olup olmadığını yasaklar .

Alıntı 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.

Ayrıca, Nginx'in HTTP 1.1 ile uyumlu doğru davranışı, HTTP isteği kaçakçılık saldırılarını önlemeye doğru uzun bir yol kat etmektedir .
amn

3

Komut dosyanızın neden başta bir yönlendirme yanıtı olmak üzere yığınlanmış kodlamaya ihtiyaç duyduğunu özellikle belirtmediniz.

Burada çok sayıda sorun görüyorum.

  • Transfer-Encoding: chunkedbir HTTP/1.1özelliktir (ve komut dosyanız bir HTTP/1.0başlıkla yanıtlıyor gibi görünüyor )

  • Hiçbir yoktur 307yılındaHTTP/1.0

  • tüm amacı, chunkedne Content-Lengtholacağınızı bilmemenizdir, bu nedenle, gerçek içerikle karıştırılmış, yanıtın gövdesi içinde uzunlukların sağlandığı yerde chunkeduzunluk sağlamak için kullanılır Content-Length; bir komut dosyasının her iki üstbilgiyi de önceden oluşturması anlamsız olurdu

Kişisel olarak aşina değilim chunked, ancak http://en.wikipedia.org/wiki/Chunked_transfer_encoding ve ayrıca http://tools.ietf.org/html/rfc2616#section-3.6.1 adresindeki temel bilgilere göre , Komut dosyanızın yığınlanmış kodlamayı tümüyle ele almasının tamamen yanlış olabileceğini tahmin ediyorum.

Yukarıdakiler hala kapsamıyorsa ve aksi halde tümüyle gerçekte, bir 307veya 302http durum koduna sahip bir yanıtın neden "garip" kodlama ile sağlanması gerektiği açık değildir . Son zamanlarda benzer bir tartışma nginx posta listesinde 410 Goneve diğer hata sayfaları her zaman gzipsıkıştırma dışında tutuldu ve sanırım burada eşit derecede geçerli olacaktır. ( http://mailman.nginx.org/pipermail/nginx/2013-Martch/037890.html )


Kullanıcıyı bekletmek için kullanıyorum: Her saniye parçalar gönderiyorum, böylece kullanıcı zaman aşımı olmadan X saniye boyunca yeniden yönlendirmeyi bekleyecek
Julien

Ben (bu şeyler / 1.0 HTTP / 1.1 ilk düzeltme HTTP öneriyorum yapmak bir fark yaratmak), ve yığın halinde kodlama uygunsuz olmadığından emin olun. Nginx'in yeni sürümü, muhtemelen yanlış olduğunuz için bağımlı olduğunuz bazı başlıkları atar.
cnst

1

Ben html5 video etiketi ile mp4 dosya akışı aynı sorunu vardı.

Safari ve Firefox normal davrandılar, ancak Chrome bir noktada ERR_CONTENT_LENGTH_MISMATCH'yi tetikledi (ancak başarısız olmadan önce videonun birkaç dakikasını açmama izin verdi).

Mp4 dosyaları için önbellek denetimini kapattıktan sonra sorun yeniden oluşturmadı.


0

Yararlı olması durumunda SO'ya gönderdiğim bu cevabı paylaşıyorum: /programming/50499637/mp4-video-safari-cloudflare-nginx-rails-no-play/59348509#59348509

Parçaların sunulmaması nedeniyle mp4 oynatma ile benzer bir sorun yaşadım ve aşağıda listelenen Apple kılavuzuna göre sorunu doğruladım. Tüm dosyayı indirdiğimi doğruladım ve aşağıdaki düzeltmeden sonra sadece ilk yığın.

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

Ben gzip sıkıştırmasını kaldırmak için, benim nginx.conf benim Gzip sıkıştırma ayarlarını değiştirerek benim Safari .mp4 oynatmayı çözüldü .mp4 dosyaları.

İşte referans için nginx'deki blok. (Not: uygulamanızın nasıl yapılandırıldığına bağlı olarak, konum satırını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 belge referansına bağlantı: https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html#//apple_ref/doc/uid/TP4000S1465-14

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.