¿Cómo manejar correctamente una página comprimida al usar curl?

139

Escribí un script bash que obtiene resultados de un sitio web usando curl y hace un montón de manipulación de cadenas en la salida html. El problema es cuando lo ejecuto contra un sitio que está devolviendo su salida comprimida. Ir al sitio en un navegador funciona bien.

Cuando ejecuto curl a mano, obtengo un resultado comprimido:

$ curl "http://example.com"

Aquí está el encabezado de ese sitio en particular:

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

Sé que los datos devueltos están comprimidos, porque esto devuelve html, como se esperaba:

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

No quiero canalizar la salida a través de gunzip, porque el script funciona tal cual en otros sitios, y la canalización a través de gzip rompería esa funcionalidad.

Lo que he intentado

  1. cambiando el agente de usuario (probé la misma cadena que envía mi navegador, "Mozilla / 4.0", etc.)
  2. hombre rizo
  3. búsqueda de Google
  4. buscando stackoverflow

Todo salió vacío

¿Algunas ideas?

BryanH
fuente
Para mí, el problema era que el enrollamiento no fue 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) - lo resolvió mediante la eliminación brde Accept-Encoding. ver stackoverflow.com/questions/18983719/…
Nino Škopac

Respuestas:

260

curldescomprimirá automáticamente la respuesta si configura el --compressedindicador:

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

--compressed (HTTP) Solicite una respuesta comprimida utilizando uno de los algoritmos que admite libcurl, y guarde el documento sin comprimir. Si se usa esta opción y el servidor envía una codificación no compatible, curl informará un error.

Lo más probable es que sea compatible con gzip, pero puede verificar esto ejecutando curl -Vy buscando libz en algún lugar de la línea "Características":

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

Tenga en cuenta que es realmente el sitio web en cuestión el que tiene la culpa aquí. Si curlno pasó un Accept-Encoding: gzipencabezado de solicitud, el servidor no debería haber enviado una respuesta comprimida.

Martín
fuente
24
Esto parecería ser un error curl, ya que debería activar su decodificación en función de la respuesta, no de lo que solicitó (dado que admite gzip). Para citar HTTP 1.1: "Si no hay un campo de Codificación de aceptación presente en una solicitud, el servidor PUEDE asumir que el cliente aceptará cualquier codificación de contenido". Pero continúa diciendo que los servidores DEBEN en ese caso no codificar el contenido, hmm, imagínense.
George Lund
en realidad en mi versión funciona --comp --compress --compressed
Radu Toader
3
esto también establece el encabezado de la solicitud: "Accept-Encoding: deflate, gzip", eso es genial ya que si el servidor sirve gzip y no gzip, solo necesita --comprimido y no agregar el encabezado de codificación de aceptación usted mismo
mbert
¡ayude a mi control de calidad con esta solución en 1 minuto! gracias ! Dicho esto, mi aplicación en realidad está enviando una respuesta gzip con Content-Encoding: gzip. Los navegadores y las herramientas modernas (por ejemplo, httpie) lo manejan automáticamente. Supongo que los rizos solo necesitan una "pista"
Faraway
Sorprendentemente, la configuración Accept-Encoding: deflate, gzipno es suficiente, incluso si el servidor devuelve una respuesta gzip con Content-Encoding: gzip, curl no lo descomprimirá automáticamente. Se --compressedrequiere la bandera.
rjh