Làm thế nào để xử lý đúng một trang được nén khi sử dụng curl?


139

Tôi đã viết một tập lệnh bash nhận đầu ra từ một trang web bằng cách sử dụng curl và thực hiện một loạt các thao tác chuỗi trên đầu ra html. Vấn đề là khi tôi chạy nó trên một trang web đang trả lại đầu ra của nó được nén. Đi đến trang web trong một trình duyệt hoạt động tốt.

Khi tôi chạy curl bằng tay, tôi nhận được đầu ra được nén:

$ curl "http://example.com"

Đây là tiêu đề từ trang web cụ thể đó:

HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=utf-8
X-Powered-By: PHP/5.2.17
Last-Modified: Sat, 03 Dec 2011 00:07:57 GMT
ETag: "6c38e1154f32dbd9ba211db8ad189b27"
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Cache-Control: must-revalidate
Content-Encoding: gzip
Content-Length: 7796
Date: Sat, 03 Dec 2011 00:46:22 GMT
X-Varnish: 1509870407 1509810501
Age: 504
Via: 1.1 varnish
Connection: keep-alive
X-Cache-Svr: p2137050.pubip.peer1.net
X-Cache: HIT
X-Cache-Hits: 425

Tôi biết dữ liệu trả về được nén, bởi vì điều này trả về html, như mong đợi:

$ curl "http://example.com" | gunzip

Tôi không muốn chuyển đầu ra qua gunzip, vì tập lệnh hoạt động như trên các trang web khác và đường ống qua gzip sẽ phá vỡ chức năng đó.

Những gì tôi đã thử

  1. thay đổi tác nhân người dùng (Tôi đã thử cùng một chuỗi trình duyệt của tôi gửi, "Mozilla / 4.0", v.v.)
  2. người đàn ông cuộn tròn
  3. tìm kiếm trên google
  4. tìm kiếm stackoverflow

Mọi thứ trở nên trống rỗng

Có ý kiến ​​gì không?


Đối với tôi, vấn đề là cURL không thể giải nén Brotli ( curl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0) - đã giải quyết nó bằng cách xóa brkhỏi Accept-Encoding. xem stackoverflow.com/questions/18983719/ khăn
Nino kopac

Câu trả lời:


260

curlsẽ tự động giải nén phản hồi nếu bạn đặt --compressedcờ:

curl --compressed "http://example.com"

--compced (HTTP) Yêu cầu phản hồi nén bằng một trong các thuật toán hỗ trợ libcurl và lưu tài liệu không nén. Nếu tùy chọn này được sử dụng và máy chủ gửi mã hóa không được hỗ trợ, curl sẽ báo lỗi.

gzip rất có thể được hỗ trợ, nhưng bạn có thể kiểm tra điều này bằng cách chạy curl -Vvà tìm libz ở đâu đó trong dòng "Tính năng":

$ curl -V
...
Protocols: ...
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz 

Lưu ý rằng đó thực sự là trang web được đề cập có lỗi ở đây. Nếu curlkhông vượt qua Accept-Encoding: gziptiêu đề yêu cầu, máy chủ sẽ không gửi phản hồi nén.


24
Đây có vẻ là một lỗi curl, bởi vì nó sẽ kích hoạt giải mã dựa trên phản hồi, chứ không phải dựa trên những gì nó yêu cầu (với điều kiện là nó hỗ trợ gzip). Để trích dẫn HTTP 1.1: "Nếu không có trường Mã hóa chấp nhận có trong yêu cầu, máy chủ CÓ THỂ cho rằng máy khách sẽ chấp nhận bất kỳ mã hóa nội dung nào." Nhưng nó tiếp tục nói rằng các máy chủ NÊN trong trường hợp đó không mã hóa nội dung, hmm, đi con số.
George Lund

thực sự trên phiên bản của tôi hoạt động
Radu Toader

3
này cũng đặt tiêu đề yêu cầu: "Accept-Encoding: deflate, gzip" Thats lớn vì nếu máy chủ phục vụ gzip và không gzip, bạn chỉ cần --compressed và không thêm tiêu đề chấp nhận mã hóa bản thân
mbert

giúp QA của tôi với giải pháp này trong 1 phút! cảm ơn bạn ! Điều đó nói rằng, ứng dụng của tôi thực sự đang gửi phản hồi gzip với Content-Encoding: gzip. Trình duyệt và các công cụ hiện đại (ví dụ httpie) tự động xử lý nó. Tôi đoán curl chỉ cần một "gợi ý"
Faraway

Đáng ngạc nhiên, cài đặt Accept-Encoding: deflate, gziplà không đủ - ngay cả khi máy chủ trả về phản hồi gzip với Content-Encoding: gzip, curl sẽ không tự động giải nén nó. Các --compressedlá cờ là bắt buộc.
rjh
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.