Nginx xóa tiêu đề Độ dài nội dung cho nội dung chunk


10

Tôi sử dụng nginx 1.2.3 để ủy quyền cho tập lệnh:

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

Các tập lệnh gửi cả 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

Tôi cần cả hai, nhưng nginx sẽ tự động xóa 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: /...

Do đó, các khách hàng không chờ đợi các khối được gửi. Điều này được sử dụng để làm việc với một phiên bản trước đó của nginx.


Các tiêu đề trông như thế nào từ proxy nginx?
hrunting

Phiên bản nào đã được sử dụng để làm việc với?
cnst

Nó được sử dụng để làm việc với nginx 0.9.8
Julien

Bạn đang vi phạm giao thức HTTP. Nó hoạt động với nginx 0.9.8, vì cho đến phiên bản 1.1.4, nó hoàn toàn không hỗ trợ mã hóa chunk.
VBart

Câu trả lời:


11

Thật không may, tôi không thể nhận xét về bài đăng của cnst - vì vậy tôi sẽ trả lời ở đây.

Các nginx_http_proxymô-đun bằng cách đàm phán mặc định với thượng nguồn trong HTTP / 1.0. Điều này có thể được thay đổi với chỉ thị proxy_http_version 1.1.

Đây cũng có thể là nguyên nhân khiến tập lệnh của bạn trả về câu trả lời HTTP / 1.0, mặc dù mã hóa và mã trạng thái được mã hóa 307không tồn tại trong phiên bản này.

Bạn cũng không nên sử dụng mã hóa chunk với chuyển hướng , vì điều này không thực sự có ý nghĩa.

Ngoài ra , có vẻ như nginx không truyền từng phần từ thượng nguồn cho khách hàng từng cái một, nhưng nó đệm phản ứng ngược dòng . Trường Content-Lengthtiêu đề bị bỏ qua vì nó trái với định nghĩa. Tôi đã phải xem mã nguồn của mô-đun vì tất cả điều này dường như không có giấy tờ.

Bạn có thể muốn dùng thử nginx_tcp_proxy_moduleđể ủy quyền nội dung chunk dưới dạng dữ liệu TCP thô: Mô-đun tại Github


CẬP NHẬT (10.04.14)
Các nginx_http_proxymô-đun đã hỗ trợ cho X-Accel-* tiêu đề , trong đó có một ( X-Accel-Buffering: yes|no) điều khiển cho dù phản ứng nên được đệm hay không.

Thêm tiêu đề này ( X-Accel-Buffering: no) vào phản hồi của phụ trợ sẽ khiến nginx truyền trực tiếp các đoạn cho khách hàng.

Tiêu đề này cho phép kiểm soát bộ đệm trên cơ sở mỗi yêu cầu .

Mô-đun này cũng có một chỉ thị cấu hình proxy_buffering để bật hoặc tắt bộ đệm phản hồi (không đệm có nghĩa là gửi khối sẽ hoạt động).

Bộ đệm proxy (cả tiêu đề và chỉ thị) được ghi lại ở đây .


Anh ta không nên làm điều đó ngay cả với nginx_tcp_proxy_module. Nó chỉ hoạt động với một số trình duyệt vì chúng rất dễ chịu lỗi.
VBart

bởi vì tất cả điều này dường như là không có giấy tờ . Nó được ghi lại trong RFC 2616. Xem 13.5.1 .
VBart

@VBart Chắc chắn có các tiêu chuẩn - nhưng chỉ có rất ít thông tin về việc nginx thực hiện chúng đến mức nào . Mô-đun proxy TCP đang có một cách giải quyết được đề xuất .
Lukas

9

Như Lukas ám chỉ, HTTP 1.1 nghiêm cấm Content-Lengthnếu có một Transfer-Encodingbộ.

Trích dẫn 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.

Ngoài ra, hành vi đúng của Nginx tuân thủ HTTP 1.1 sẽ giúp ngăn chặn các cuộc tấn công buôn lậu yêu cầu HTTP .
Amn

3

Bạn chưa giải thích cụ thể tại sao tập lệnh của bạn cần mã hóa chunk ngay từ đầu, đặc biệt là với phản hồi chuyển hướng.

Tôi thấy vô số vấn đề ở đây.

  • Transfer-Encoding: chunkedlà một HTTP/1.1tính năng (và tập lệnh của bạn dường như đang trả lời bằng một HTTP/1.0tiêu đề)

  • không có 307trongHTTP/1.0

  • toàn bộ mục đích chunkedlà bạn không biết những gì bạn Content-Lengthsẽ có, vì vậy, chunkedđược sử dụng thay cho việc cung cấp độ dài bên trong Content-Length, thay vào đó độ dài được cung cấp trong phần nội dung của phản hồi, được trộn lẫn với nội dung thực tế; sẽ là vô nghĩa khi một kịch bản tạo ra cả hai tiêu đề trả trước

Tôi không quen thuộc với cá nhân chunked, nhưng theo thông tin cơ bản tại http://en.wikipedia.org/wiki/Chunked_transfer_encoding và cả http://tools.ietf.org/html/rfc2616#section-3.6.1 , Tôi dự đoán rằng toàn bộ việc xử lý mã hóa đoạn mã của bạn có thể sai hoàn toàn.

Nếu ở trên vẫn không bao gồm nó, và trong thực tế khác, thì cũng không rõ tại sao một câu trả lời với mã trạng thái 307hoặc 302http nên được cung cấp với một mã hóa "lạ". Gần đây có một cuộc thảo luận tương tự trong danh sách gửi thư nginx 410 Gonevà các trang lỗi khác luôn bị loại trừ khỏi việc gzipnén và tôi nghĩ rằng tình cảm sẽ được áp dụng tương tự ở đây. ( http://mailman.nginx.org/pipermail/nginx/2013-March/037890.html )


Tôi sử dụng nó để khiến người dùng chờ đợi: Tôi gửi các khối mỗi giây, để người dùng sẽ chờ chuyển hướng trong X giây mà không bị hết thời gian
Julien

Trước tiên, tôi khuyên bạn nên sửa HTTP / 1.0 thành HTTP / 1.1 (những điều này tạo ra sự khác biệt) và đảm bảo mã hóa khối của bạn không sai. Phiên bản mới hơn của nginx có thể loại bỏ một số tiêu đề mà bạn phụ thuộc vì chúng sai.
cnst

1

Tôi gặp vấn đề tương tự khi phát trực tuyến tệp mp4 qua thẻ video html5.

Safari và Firefox hoạt động bình thường trong khi Chrome đã kích hoạt ERR_CONTENT_LENGTH_MISMATCH tại một số điểm (nhưng nó cho phép tôi lướt qua vài phút video trước khi thất bại).

Sự cố không được tái tạo sau khi tôi tắt điều khiển bộ đệm cho các tệp mp4.


0

Chia sẻ câu trả lời này tôi đã đăng lên SO trong trường hợp hữu ích: /programming/50499637/mp4-video-safari-cloudflare-nginx-rails-no-play/59348509#59348509

Tôi gặp vấn đề tương tự với phát lại mp4 do các đoạn không được phục vụ và đã xác nhận sự cố theo hướng dẫn của Apple, được liệt kê bên dưới. Tôi xác nhận rằng tôi đã tải xuống toàn bộ tệp và sau khi sửa lỗi bên dưới, chỉ có đoạn đầu tiên.

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

Tôi đã giải quyết phát lại Safari .mp4 bằng cách thay đổi cài đặt nén gzip của mình trong nginx.conf, để xóa nén gzip các tệp .mp4 .

Đây là khối trong nginx để tham khảo. (Lưu ý: tùy thuộc vào cách ứng dụng của bạn được định cấu hình, bạn có thể cần thay đổi dòng vị trí thànhlocation ~ \.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;
}

Liên kết với tài liệu tham khảo của Apple: https://developer.apple.com/l Library / archive / document / AppleAppluggest / Reperence / SalariWebContent / CreatingVideoforSafarioniPhone / CateingVideoforSafarioniPhone.html / //

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.