Commit 0790b279 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

HTTP: add support for gzip and deflate Transfer-Encoding

Transfer-Encoding differs from Content-Encoding in a few subtle ways,
but primarily it concerns the transfer only and not the content so when
discovered to be compressed we know we have to uncompress it. There will
only arrive compressed transfers in a response after we have requested
them with the appropriate TE: header.

Test case 1122 and 1123 verify.
parent e80b9577
Loading
Loading
Loading
Loading
+67 −5
Original line number Diff line number Diff line
@@ -1728,6 +1728,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
      return CURLE_OUT_OF_MEMORY;
  }

#if 0
  if(!Curl_checkheaders(data, "TE:")) {
    Curl_safefree(conn->allocptr.te);
    conn->allocptr.te = aprintf("TE: %s\r\n", "gzip");
    if(!conn->allocptr.te)
      return CURLE_OUT_OF_MEMORY;
  }
#endif

  ptr = Curl_checkheaders(data, "Transfer-Encoding:");
  if(ptr) {
    /* Some kind of TE is requested, check if 'chunked' is chosen */
@@ -2058,6 +2067,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
                "%s" /* user agent */
                "%s" /* host */
                "%s" /* accept */
                "%s" /* TE: */
                "%s" /* accept-encoding */
                "%s" /* referer */
                "%s" /* Proxy-Connection */
@@ -2075,6 +2085,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
                conn->allocptr.uagent:"",
                (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
                http->p_accept?http->p_accept:"",
                conn->allocptr.te?conn->allocptr.te:"",
                (data->set.str[STRING_ENCODING] &&
                 *data->set.str[STRING_ENCODING] &&
                 conn->allocptr.accept_encoding)?
@@ -3127,8 +3138,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
       */
      conn->bits.close = TRUE; /* close when done */
    }
    else if(Curl_compareheader(k->p, "Transfer-Encoding:", "chunked") &&
            !(conn->handler->protocol & CURLPROTO_RTSP)) {
    else if(checkprefix("Transfer-Encoding:", k->p)) {
      /* One or more encodings. We check for chunked and/or a compression
         algorithm. */
      /*
       * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
       * means that the server will send a series of "chunks". Each
@@ -3137,10 +3149,60 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
       * with the previously mentioned size. There can be any amount
       * of chunks, and a chunk-data set to zero signals the
       * end-of-chunks. */

      char *start;

      /* Find the first non-space letter */
      start = k->p + 18;

      do {
        /* skip whitespaces and commas */
        while(*start && (ISSPACE(*start) || (*start == ',')))
          start++;

        if(checkprefix("chunked", start)) {
          k->chunk = TRUE; /* chunks coming our way */

          /* init our chunky engine */
          Curl_httpchunk_init(conn);

          start += 7;
        }

        if(k->content_encoding)
          /* TODO: we only support the first mentioned compression for now */
          break;

        if(checkprefix("identity", start)) {
          k->content_encoding = IDENTITY;
          start += 8;
        }
        else if(checkprefix("deflate", start)) {
          k->content_encoding = DEFLATE;
          start += 7;
        }
        else if(checkprefix("gzip", start)) {
          k->content_encoding = GZIP;
          start += 4;
        }
        else if(checkprefix("x-gzip", start)) {
          k->content_encoding = GZIP;
          start += 6;
        }
        else if(checkprefix("compress", start)) {
          k->content_encoding = COMPRESS;
          start += 8;
        }
        else if(checkprefix("x-compress", start)) {
          k->content_encoding = COMPRESS;
          start += 10;
        }
        else
          /* unknown! */
          break;

      } while(1);

    }
    else if(checkprefix("Content-Encoding:", k->p) &&
            data->set.str[STRING_ENCODING]) {
+1 −0
Original line number Diff line number Diff line
@@ -2549,6 +2549,7 @@ static void conn_free(struct connectdata *conn)
  Curl_safefree(conn->allocptr.uagent);
  Curl_safefree(conn->allocptr.userpwd);
  Curl_safefree(conn->allocptr.accept_encoding);
  Curl_safefree(conn->allocptr.te);
  Curl_safefree(conn->allocptr.rangeline);
  Curl_safefree(conn->allocptr.ref);
  Curl_safefree(conn->allocptr.host);
+12 −11
Original line number Diff line number Diff line
@@ -837,18 +837,19 @@ struct connectdata {
                                well be the same we read from.
                                CURL_SOCKET_BAD disables */

  /** Dynamicly allocated strings, may need to be freed before this **/
  /** Dynamicly allocated strings, MUST be freed before this **/
  /** struct is killed.                                      **/
  struct dynamically_allocated_data {
    char *proxyuserpwd; /* free later if not NULL! */
    char *uagent; /* free later if not NULL! */
    char *accept_encoding; /* free later if not NULL! */
    char *userpwd; /* free later if not NULL! */
    char *rangeline; /* free later if not NULL! */
    char *ref; /* free later if not NULL! */
    char *host; /* free later if not NULL */
    char *cookiehost; /* free later if not NULL */
    char *rtsp_transport; /* free later if not NULL */
    char *proxyuserpwd;
    char *uagent;
    char *accept_encoding;
    char *userpwd;
    char *rangeline;
    char *ref;
    char *host;
    char *cookiehost;
    char *rtsp_transport;
    char *te; /* TE: request header */
  } allocptr;

  int sec_complete; /* if kerberos is enabled for this connection */
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
 test1203 test1117 test1118 test1119 test1120 test1300 test1301 test1302 \
 test1303 test320 test321 test322 test323 test324 test1121 test581 test580 \
 test1304 test1305 test1306 test1307 test582 test583 test808 test809       \
 test810 test811 test812 test813 test584
 test810 test811 test812 test813 test584 test1122 test1123

filecheck:
	@mkdir test-place; \

tests/data/test1122

0 → 100644
+69 −0
Original line number Diff line number Diff line
<testcase>
<info>
<keywords>
HTTP
HTTP GET
compressed
Transfer-Encoding
</keywords>
</info>
#
# Server-side
<reply>
<data base64="yes">
SFRUUC8xLjEgMjAwIE9LDQpEYXRlOiBNb24sIDI5IE5vdiAyMDA0IDIxOjU2OjUzIEdNVA0KU2Vy
dmVyOiBBcGFjaGUvMS4zLjMxIChEZWJpYW4gR05VL0xpbnV4KSBtb2RfZ3ppcC8xLjMuMjYuMWEg
UEhQLzQuMy45LTEgbW9kX3NzbC8yLjguMjAgT3BlblNTTC8wLjkuN2QgbW9kX3BlcmwvMS4yOQ0K
VmFyeTogQWNjZXB0LUVuY29kaW5nDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1J
U08tODg1OS0xDQpUcmFuc2Zlci1FbmNvZGluZzogZ3ppcA0KQ29udGVudC1MZW5ndGg6IDQ0DQoN
Ch+LCAh5nqtBAANsYWxhbGEAy8nMS1Uw5FLIAdFGXAoQhjEXAAoCcWAYAAAA
</data>

<datacheck>
HTTP/1.1 200 OK
Date: Mon, 29 Nov 2004 21:56:53 GMT
Server: Apache/1.3.31 (Debian GNU/Linux) mod_gzip/1.3.26.1a PHP/4.3.9-1 mod_ssl/2.8.20 OpenSSL/0.9.7d mod_perl/1.29
Vary: Accept-Encoding
Content-Type: text/html; charset=ISO-8859-1
Transfer-Encoding: gzip
Content-Length: 44

line 1
 line 2
  line 3
</datacheck>

</reply>

#
# Client-side
<client>
<features>
libz
</features>
<server>
http
</server>
 <name>
HTTP GET gzip transfer-encoded content
 </name>
 <command>
http://%HOSTIP:%HTTPPORT/1122 -H "TE: gzip"
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1122 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
TE: gzip

</protocol>
</verify>
</testcase>
Loading