cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: [PATCH] Addition of trailer headers in HTTP requests generated by libcurl

From: Chrysovaladis Datsios <cdatsios_at_gmail.com>
Date: Thu, 21 Feb 2013 10:23:46 +0200

Hi,
I'm sending you a new version of the patch. It is attached.

> 0 - you didn't really follow our code style when it comes to indenting. A
> minor nit, but still...
I tried to keep it, but the mail formater wash it off :)

>
> 1 - Can you think of a good reason why the callback would need to get the
> struct curl_slist * as its second argument? Won't that always just be
> NULL?
No. Now it is removed.

>
> 2 - since the trailer headers now are set by a return code from a callback,
> I don't think they should be part of the 'struct UserDefined' anymore.
> In fact, is there a point to have it stored within the SessionHandle
> struct at all?
I moved it at the connectdata struct.

>
> 3 - the memcpy() functions invoked after the callback has returned its list
> of headers are not checking that the destination is big enough. It
> uses the data set by the callback which risk overflowing the upload
> buffer...
You're right, now I allocate specific space for the list of headers

>
> 4 - I asked you before, but why is_trailerheaders_set? You can just as well
> save 5 lines of code and some memory by checking 'trailerheaders_func'
> instead!
Removed it.

>
> 5 - you modified a file in src/ without purpose.
Removed. Sorry for the dead code.

Following are a small documentation & an example code using it.
+------------------------------+
| documentation |
+------------------------------+

curl_easy_setopt() option: CURLOPT_TRAILERFUNCTION

Pass a pointer to a function that matches the following prototype:
struct curl_slist* function(CURL *handle, void *userdata); This
function gets called by libcurl when it is to send the last chunk of
(zero payload)data to the peer. Chunked transfer-encoding must be
used. The trailer header names have to be set in advance as custom
headers using the CURLOPT_HTTPHEADER option with "Trailer" as "header
name_field" and the actual header name as "header value_field". Inside
the callback function a linked list of type struct curl_slist that
will contain the trailer headers have to be created using the
curl_slist_append(3) function. The callback function returns a pointer
to the trailer_headers list. The user also can pass in a custom
pointer to the callback, this is done by the associated
CURLOPT_TRAILERDATA option.

curl_easy_setopt() option: CURLOPT_TRAILERDATA
Data pointer to pass to the trailer function. If you use the
CURLOPT_TRAILERFUNCTION option, this is the pointer you'll get as
input.

        
+----------------------------------------------+
| code example: |
| PUT request with trailer header |
+----------------------------------------------+
#include <stdio.h>
#include <curl/curl.h>
#include <sys/stat.h>
#include <fcntl.h>

/* trailer header setting callback function */
struct curl_slist * trailerheader_callback(CURL *handle, void *userdata) {
  int *code = (int *)userdata;
  struct curl_slist *trailer_headers;
  if(!(*code))
    trailer_headers = curl_slist_append(trailer_headers, "mytrailer: EOF");
  else
    trailer_headers = curl_slist_append(trailer_headers, "mytrailer: error");

  return trailer_headers;
}

int main(void)
{
  CURL *curl;
  CURLcode res;
  int filecode;
  FILE *fd;
  struct curl_slist *custom_http_hdrs=NULL;

  fd = fopen("video_0000", "rb"); /* open file to upload */
  if(!fd) {
    return 1; /* can't continue */
  }

  /* Read callback function */
  size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream) {
    size_t retcode;

    retcode = fread(ptr, size, nmemb, stream);
    if(!retcode) {
      if(ferror(stream))
        filecode = 1;
      if(feof(stream))
        filecode = 0;
    }
    return retcode;
  }

  curl = curl_easy_init();
  if(curl) {

    curl_easy_setopt(curl, CURLOPT_URL, "http://10.8.60.209/myfile");

    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(curl, CURLOPT_READDATA, fd);
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

    custom_http_hdrs = curl_slist_append(custom_http_hdrs,
"Transfer-Encoding: chunked");
    custom_http_hdrs = curl_slist_append(custom_http_hdrs, "Trailer:
mytrailer");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, custom_http_hdrs);

    curl_easy_setopt(curl, CURLOPT_TRAILERFUNCTION, trailerheader_callback);
    curl_easy_setopt(curl, CURLOPT_TRAILERDATA, &filecode);

    res = curl_easy_perform(curl);

    if(res != CURLE_OK) {
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
    }
    fclose(fd);
    curl_slist_free_all(custom_http_hdrs);
    curl_easy_cleanup(curl);
  }
  return 0;
}

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html

Received on 2013-02-21