Hi, this is a patch for the feature request as described in http://sourceforge.net/p/curl/feature-requests/67/ the feature is a standard in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.40
One can also refer at Chris Shiflett's Book "HTTP: Developer's Handbook" from SAMS page 97. http://books.google.gr/books?isbn=0672324547 Example case: Chunked PUT request with Trailer headers. PUT /myfile HTTP/1.1 Host: 10.8.60.209 Accept: / Transfer-Encoding: chunked Trailer: mytrailerheader Expect: 100-continue 53 ....first chunk of data...... 53 .....second chunk of data..... 0 mytrailerheader: myvalue ---------------------------------- The feature is implemented as another in curl_easy_setopt() function. This new option is named CURLOPT_HTTPTRAILERHEADER and adds the trailer headers appended on a curl_slist. Example code snippet using the new feature: struct curl_slist *trailer_http_hdrs; trailer_http_hdrs = curl_slist_append(trailer_http_hdrs, "mytrailerheader: myvalue"); curl_easy_setopt(curl, CURLOPT_HTTPTRAILERHEADER, trailer_http_hdrs); ---------------------------------- This are the diffs from the original library: curl-7.28.1 I hope it makes it to be included in a future verson. diff -ur curl_orig/include/curl/curl.h curl_new/include/curl/curl.h --- curl_orig/include/curl/curl.h 2012-09-26 12:46:15.000000000 +0300 +++ curl_new/include/curl/curl.h 2013-01-17 12:31:24.000460704 +0200 @@ -1536,6 +1536,9 @@ /* set the SMTP auth originator */ CINIT(MAIL_AUTH, OBJECTPOINT, 217), + /* points to a linked list of trailer headers, struct curl_slist kind */ + CINIT(HTTPTRAILERHEADER, OBJECTPOINT, 218), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff -ur curl_orig/lib/http.c curl_new/lib/http.c --- curl_orig/lib/http.c 2012-11-13 23:02:16.000000000 +0200 +++ curl_new/lib/http.c 2013-01-17 12:33:20.817372849 +0200 @@ -1524,6 +1524,9 @@ char *ptr; struct curl_slist *headers=conn->data->set.headers; + char *tptr; + struct curl_slist *trailer_headers=conn->data->set.trailer_headers; + while(headers) { ptr = strchr(headers->data, ':'); if(ptr) { @@ -1590,6 +1593,31 @@ } headers = headers->next; } + + while(trailer_headers) { + ptr = strchr(trailer_headers->data, ':'); + if(ptr) { + tptr = --ptr; /* the point where the trailer header field ends */ + ptr++; /* pass the colon */ + while(*ptr && ISSPACE(*ptr)) + ptr++; + + if(*ptr) { + /* only send this if the contents was non-blank */ + + char tfield[CURL_MAX_HTTP_HEADER]; + strncpy(tfield, trailer_headers->data, tptr-trailer_headers->data+1); + tfield[tptr-trailer_headers->data+1] = '\0'; + CURLcode result = Curl_add_bufferf(req_buffer, "Trailer: %s\r\n", + tfield); + tptr = NULL; + if(result) + return result; + } + } + trailer_headers = trailer_headers->next; + } + return CURLE_OK; } diff -ur curl_orig/lib/transfer.c curl_new/lib/transfer.c --- curl_orig/lib/transfer.c 2012-11-13 23:02:16.000000000 +0200 +++ curl_new/lib/transfer.c 2013-01-17 12:33:40.002719777 +0200 @@ -929,6 +929,34 @@ that instead of reading more data */ } + /* The last chunk has zero size of data i.e. 0\r\n*/ + if(k->upload_chunky == true && data->req.upload_present == 5 && + !strncmp(data->req.upload_fromhere, "0\r\n", 3) ) { + + Curl_send_buffer *trailer_buffer = Curl_add_buffer_init(); + result = Curl_add_bufferf(trailer_buffer, "0\r\n"); + if(result) + return result; + + char *ptr; + struct curl_slist *trailer_headers=conn->data->set.trailer_headers; + while(trailer_headers) { + ptr = strchr(trailer_headers->data, ':'); + if(ptr) { + result = Curl_add_bufferf(trailer_buffer, "%s\r\n", + trailer_headers->data); + if(result) + return result; + } + trailer_headers = trailer_headers->next; + } + result = Curl_add_bufferf(trailer_buffer, "\r\n"); + if(result) + return result; + data->req.upload_fromhere = trailer_buffer->buffer; + data->req.upload_present = trailer_buffer->size_used; + } + /* write to socket (send away data) */ result = Curl_write(conn, conn->writesockfd, /* socket to send to */ diff -ur curl_orig/lib/url.c curl_new/lib/url.c --- curl_orig/lib/url.c 2012-11-18 16:08:45.000000000 +0200 +++ curl_new/lib/url.c 2013-01-17 12:32:59.583027669 +0200 @@ -1261,6 +1261,13 @@ data->set.headers = va_arg(param, struct curl_slist *); break; + case CURLOPT_HTTPTRAILERHEADER: + /* + * Set a list with HTTP trailer headers to use + */ + data->set.trailer_headers = va_arg(param, struct curl_slist *); + break; + case CURLOPT_HTTP200ALIASES: /* * Set a list of aliases for HTTP 200 in response header diff -ur curl_orig/lib/urldata.h curl_new/lib/urldata.h --- curl_orig/lib/urldata.h 2012-11-13 23:02:16.000000000 +0200 +++ curl_new/lib/urldata.h 2013-01-17 12:33:07.634950493 +0200 @@ -1466,6 +1466,7 @@ download */ curl_off_t set_resume_from; /* continue [ftp] transfer from here */ struct curl_slist *headers; /* linked list of extra headers */ + struct curl_slist *trailer_headers; /* linked list of trailer headers */ struct curl_httppost *httppost; /* linked list of POST data */ bool cookiesession; /* new cookie session? */ bool crlf; /* convert crlf on ftp upload(?) */ diff -ur curl_orig/src/tool_cfgable.h curl_new/src/tool_cfgable.h --- curl_orig/src/tool_cfgable.h 2012-08-08 23:45:18.000000000 +0300 +++ curl_new/src/tool_cfgable.h 2013-01-17 12:32:19.411456442 +0200 @@ -150,6 +150,7 @@ curl_TimeCond timecond; time_t condtime; struct curl_slist *headers; + struct curl_slist *trailer_headers; struct curl_httppost *httppost; struct curl_httppost *last_post; struct curl_slist *telnet_options; diff -ur curl_orig/src/tool_operate.c curl_new/src/tool_operate.c --- curl_orig/src/tool_operate.c 2012-11-13 23:02:16.000000000 +0200 +++ curl_new/src/tool_operate.c 2013-01-17 12:32:35.467278692 +0200 @@ -978,6 +978,7 @@ my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer); my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent); my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers); + my_setopt_slist(curl, CURLOPT_HTTPTRAILERHEADER, config->headers); /* new in libcurl 7.5 */ my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs); ------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html
