mirror of
https://github.com/curl/curl.git
synced 2026-08-25 12:43:37 +03:00
Adrian Schuur added trailer support in the chunked encoding stream. The
trailer is then sent to the normal header callback/stream.
This commit is contained in:
parent
86660c73e5
commit
465e19dbe9
9 changed files with 200 additions and 9 deletions
|
|
@ -153,10 +153,17 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||
if(*datap == '\n') {
|
||||
/* we're now expecting data to come, unless size was zero! */
|
||||
if(0 == ch->datasize) {
|
||||
ch->state = CHUNK_STOP; /* stop reading! */
|
||||
if(1 == length) {
|
||||
/* This was the final byte, return right now */
|
||||
return CHUNKE_STOP;
|
||||
if (conn->bits.trailerHdrPresent!=TRUE) {
|
||||
/* No Trailer: header found - revert to original Curl processing */
|
||||
ch->state = CHUNK_STOP;
|
||||
if (1 == length) {
|
||||
/* This is the final byte, return right now */
|
||||
return CHUNKE_STOP;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ch->state = CHUNK_TRAILER; /* attempt to read trailers */
|
||||
conn->trlPos=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -250,6 +257,64 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
|||
return CHUNKE_BAD_CHUNK;
|
||||
break;
|
||||
|
||||
case CHUNK_TRAILER:
|
||||
/* conn->trailer is assumed to be freed in url.c on a
|
||||
connection basis */
|
||||
if (conn->trlPos >= conn->trlMax) {
|
||||
char *ptr;
|
||||
if(conn->trlMax) {
|
||||
conn->trlMax *= 2;
|
||||
ptr = (char*)realloc(conn->trailer,conn->trlMax);
|
||||
}
|
||||
else {
|
||||
conn->trlMax=128;
|
||||
ptr = (char*)malloc(conn->trlMax);
|
||||
}
|
||||
if(!ptr)
|
||||
return CHUNKE_OUT_OF_MEMORY;
|
||||
conn->trailer = ptr;
|
||||
}
|
||||
conn->trailer[conn->trlPos++]=*datap;
|
||||
|
||||
if(*datap == '\r')
|
||||
ch->state = CHUNK_TRAILER_CR;
|
||||
else {
|
||||
datap++;
|
||||
length--;
|
||||
}
|
||||
break;
|
||||
|
||||
case CHUNK_TRAILER_CR:
|
||||
if(*datap == '\r') {
|
||||
ch->state = CHUNK_TRAILER_POSTCR;
|
||||
datap++;
|
||||
length--;
|
||||
}
|
||||
else
|
||||
return CHUNKE_BAD_CHUNK;
|
||||
break;
|
||||
|
||||
case CHUNK_TRAILER_POSTCR:
|
||||
if (*datap == '\n') {
|
||||
conn->trailer[conn->trlPos++]='\n';
|
||||
conn->trailer[conn->trlPos]=0;
|
||||
if (conn->trlPos==2) {
|
||||
ch->state = CHUNK_STOP;
|
||||
return CHUNKE_STOP;
|
||||
}
|
||||
else {
|
||||
Curl_client_write(conn->data, CLIENTWRITE_HEADER,
|
||||
conn->trailer, conn->trlPos);
|
||||
}
|
||||
ch->state = CHUNK_TRAILER;
|
||||
conn->trlPos=0;
|
||||
datap++;
|
||||
length--;
|
||||
}
|
||||
else
|
||||
return CHUNKE_BAD_CHUNK;
|
||||
break;
|
||||
|
||||
case CHUNK_STOP:
|
||||
/* If we arrive here, there is data left in the end of the buffer
|
||||
even if there's no more chunks to read */
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ typedef enum {
|
|||
/* POSTCR should get a CR and nothing else, then move to POSTLF */
|
||||
CHUNK_POSTCR,
|
||||
|
||||
/* POSTLF should get a LF and nothing else, then move back to HEX as
|
||||
the CRLF combination marks the end of a chunk */
|
||||
/* POSTLF should get a LF and nothing else, then move back to HEX as the
|
||||
CRLF combination marks the end of a chunk */
|
||||
CHUNK_POSTLF,
|
||||
|
||||
/* This is mainly used to really mark that we're out of the game.
|
||||
|
|
@ -62,7 +62,22 @@ typedef enum {
|
|||
buffer! */
|
||||
CHUNK_STOP,
|
||||
|
||||
/* At this point optional trailer headers can be found, unless the next line
|
||||
is CRLF */
|
||||
CHUNK_TRAILER,
|
||||
|
||||
/* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR.
|
||||
Next char must be a LF */
|
||||
CHUNK_TRAILER_CR,
|
||||
|
||||
/* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be
|
||||
signalled If this is an empty trailer CHUNKE_STOP will be signalled.
|
||||
Otherwise the trailer will be broadcasted via Curl_client_write() and the
|
||||
next state will be CHUNK_TRAILER */
|
||||
CHUNK_TRAILER_POSTCR,
|
||||
|
||||
CHUNK_LAST /* never use */
|
||||
|
||||
} ChunkyState;
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -74,6 +89,7 @@ typedef enum {
|
|||
CHUNKE_WRITE_ERROR,
|
||||
CHUNKE_STATE_ERROR,
|
||||
CHUNKE_BAD_ENCODING,
|
||||
CHUNKE_OUT_OF_MEMORY,
|
||||
CHUNKE_LAST
|
||||
} CHUNKcode;
|
||||
|
||||
|
|
|
|||
|
|
@ -833,6 +833,20 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
/* init our chunky engine */
|
||||
Curl_httpchunk_init(conn);
|
||||
}
|
||||
|
||||
else if (checkprefix("Trailer:", k->p) ||
|
||||
checkprefix("Trailers:", k->p)) {
|
||||
/*
|
||||
* This test helps Curl_httpchunk_read() to determine to look
|
||||
* for well formed trailers after the zero chunksize record. In
|
||||
* this case a CRLF is required after the zero chunksize record
|
||||
* when no trailers are sent, or after the last trailer record.
|
||||
*
|
||||
* It seems both Trailer: and Trailers: occur in the wild.
|
||||
*/
|
||||
conn->bits.trailerHdrPresent = TRUE;
|
||||
}
|
||||
|
||||
else if (checkprefix("Content-Encoding:", k->p) &&
|
||||
data->set.encoding) {
|
||||
/*
|
||||
|
|
@ -1074,6 +1088,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
* the name says read, this function both reads and writes away
|
||||
* the data. The returned 'nread' holds the number of actual
|
||||
* data it wrote to the client. */
|
||||
|
||||
CHUNKcode res =
|
||||
Curl_httpchunk_read(conn, k->str, nread, &nread);
|
||||
|
||||
|
|
|
|||
|
|
@ -1496,6 +1496,7 @@ CURLcode Curl_disconnect(struct connectdata *conn)
|
|||
Curl_safefree(conn->allocptr.host);
|
||||
Curl_safefree(conn->allocptr.cookiehost);
|
||||
Curl_safefree(conn->ip_addr_str);
|
||||
Curl_safefree(conn->trailer);
|
||||
|
||||
/* possible left-overs from the async name resolvers */
|
||||
#if defined(USE_ARES)
|
||||
|
|
|
|||
|
|
@ -421,6 +421,10 @@ struct ConnectBits {
|
|||
LPRT doesn't work we disable it for the forthcoming
|
||||
requests */
|
||||
bool netrc; /* name+password provided by netrc */
|
||||
|
||||
bool trailerHdrPresent; /* Set when Trailer: header found in HTTP response.
|
||||
Required to determine whether to look for trailers
|
||||
in case of Transfer-Encoding: chunking */
|
||||
};
|
||||
|
||||
struct hostname {
|
||||
|
|
@ -726,6 +730,12 @@ struct connectdata {
|
|||
transfer */
|
||||
|
||||
enum { NORMAL, SOURCE3RD, TARGET3RD } xfertype;
|
||||
|
||||
/* These three are used for chunked-encoding trailer support */
|
||||
char *trailer; /* allocated buffer to store trailer in */
|
||||
int trlMax; /* allocated buffer size */
|
||||
int trlPos; /* index of where to store data */
|
||||
|
||||
};
|
||||
|
||||
/* The end of connectdata. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue