error 411 Length Required c++, libcurl PUT request

2k views Asked by At

Even though I set in header Content-Lenght I'm getting 411 error. I'm trying to send PUT request. struct curl_slist *headers = NULL;

curl = curl_easy_init();
std::string paramiters =
        "<data_file><archive>false</archive><data_type_id>0a7a184a-dcc6-452a-bcd3-52dbd2a83ea2</data_type_id><data_file_name>backwardstep.stt</data_file_name><description>connectionfile</description><job_id>264cf297-3bc7-42e1-8edc-5e2948ee62b6</job_id></data_file>";

if (curl) {

    headers = curl_slist_append(headers, "Accept: */*");
    headers = curl_slist_append(headers, "Content-Length: 123");
    headers = curl_slist_append(headers, "Content-Type: application/xml");


    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");

    curl_easy_setopt(curl, CURLOPT_URL,
            "..url/data_files/new/link_upload.xml");

    curl_easy_setopt(curl, CURLOPT_USERPWD, "[email protected]:PASS");

    curl_easy_setopt(curl, CURLOPT_HEADER, 1L);

    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, paramiters.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
            strlen(paramiters.c_str()));

    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

    res = curl_easy_perform(curl);

and this is response from SERVER:

Host: cloud...
Transfer-Encoding: chunked
Accept: */*
Content-Length: 123
Content-Type: application/xml
Expect: 100-continue

* The requested URL returned error: 411 Length Required
* Closing connection #0
2

There are 2 answers

4
rioki On

Ok, I honestly can not find your error. But you should have an example from the curl website (first google hit for "curl put c code"): http://curl.haxx.se/libcurl/c/httpput.html

Maybe mixing the easy and advanced interface confuses curl.

What confuses me are the options CURLOPT_POSTFIELDS and CURLOPT_POSTFIELDSIZE. This is a put request, so why are they even there? With PUT the arguments are in the URL. The body is opaque, at least from the perspective of HTTP.

0
eco On

You DON'T need to use a file and do NOT use custom requests, INstead set the UPLOAD and PUT options as it is specified in the documentation here:

http://curl.haxx.se/libcurl/c/httpput.html

Unlike the example above where they use a file as your data structure you can USE ANYTHING to hold your data.It's all on using a callback function with this option: CURLOPT_READFUNCTION The difference is made on how you set your callback function which only has to do two things: 1.-measure the size of your payload (your data) in bytes 2.-copy the data to the memory address that curl passes to the callback (that is the first argument on your call back function, the FIRST void pointer in this definition)

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)

That is the ptr argument.

Use memcpy to copy the data.

Take a look at this link. I ran into the same problem as you and was able to solve it using this approach,one thing YOU need to keep in mind is that you ALSO need to set the file size before sending the curl request.

How do I send long PUT data in libcurl without using file pointers?

Use CURLOPT_INFILESIZE or CURLOPT_INFILESIZE_LARGE for that.