Como lidar adequadamente com uma página compactada com gzip ao usar o curl?

139

Eu escrevi um script bash que obtém saída de um site usando curl e faz um monte de manipulação de strings na saída html. O problema é quando eu o executo em um site que está retornando sua saída compactada em gzip. Ir ao site em um navegador funciona bem.

Quando executo o enrolamento manualmente, recebo a saída compactada em gzip:

$ curl "http://example.com"

Aqui está o cabeçalho desse site específico:

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

Eu sei que os dados retornados são compactados com gzip, porque isso retorna html, conforme o esperado:

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

Eu não quero canalizar a saída através do gunzip, porque o script funciona como está em outros sites, e o canal através do gzip quebraria essa funcionalidade.

O que eu tentei

  1. alterando o user agent (tentei a mesma string que meu navegador envia, "Mozilla / 4.0", etc)
  2. homem enrolar
  3. pesquisa do Google
  4. pesquisando stackoverflow

Tudo saiu vazio

Alguma ideia?

BryanH
fonte
Para mim, o problema era que o cURL não foi capaz de descomprimir 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) - resolveu-o removendo br-o Accept-Encoding. veja stackoverflow.com/questions/18983719/…
Nino Škopac 4/18/18

Respostas:

260

curldescomprimirá automaticamente a resposta se você definir o --compressedsinalizador:

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

--compressed (HTTP) Solicite uma resposta compactada usando um dos algoritmos suportados pela libcurl e salve o documento não compactado. Se essa opção for usada e o servidor enviar uma codificação não suportada, o curl reportará um erro.

O gzip provavelmente é suportado, mas você pode verificar isso executando curl -Ve procurando a libz em algum lugar na linha "Recursos":

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

Observe que é realmente o site em questão que está com falha aqui. Se curlnão passou um Accept-Encoding: gzipcabeçalho de solicitação, o servidor não deveria ter enviado uma resposta compactada.

Martin
fonte
24
Isso parece ser um bug de curl, porque deve disparar sua decodificação com base na resposta, não no que foi solicitado (já que suporta o gzip). Para citar o HTTP 1.1: "Se nenhum campo Accept-Encoding estiver presente em uma solicitação, o servidor PODE assumir que o cliente aceitará qualquer código de conteúdo." Mas continua dizendo que, nesse caso, os servidores não devem codificar o conteúdo, hmm, vai entender.
George Lund
na verdade, na minha versão funciona --comp --compress --compressed
Radu Toader
3
isso também define o cabeçalho da solicitação: "Accept-Encoding: deflate, gzip", isso é ótimo, já que se o servidor serve gzip e não gzip, você só precisa
compactado
ajude meu controle de qualidade com esta solução em 1 minuto! obrigado ! Dito isto, meu aplicativo está realmente enviando uma resposta gzip com a codificação de conteúdo: gzip. Navegadores e ferramentas modernas (por exemplo, httpie) lidam com isso automaticamente. Eu acho onda só precisa de uma "dica"
Distante
Surpreendentemente, a configuração Accept-Encoding: deflate, gzipnão é suficiente - mesmo que o servidor retorne uma resposta gzip com Content-Encoding: gzip, o curl não descompactará automaticamente. A --compressedbandeira é obrigatória.
Rjh