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.
This commit is contained in:
Daniel Stenberg 2011-04-05 23:24:52 +02:00
parent e80b957789
commit 0790b27910
6 changed files with 349 additions and 17 deletions

View file

@ -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. */
k->chunk = TRUE; /* chunks coming our way */
/* init our chunky engine */
Curl_httpchunk_init(conn);
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]) {

View file

@ -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);

View file

@ -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 **/
/** struct is killed. **/
/** 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 */