cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Question about Content-type: multipart

From: Waitman Gobble <gobble.wa_at_gmail.com>
Date: Mon, 7 Mar 2016 00:10:13 -0800

On Sun, Mar 6, 2016 at 11:43 PM, Ray Satiro via curl-library
<curl-library_at_cool.haxx.se> wrote:
> On 3/7/2016 1:15 AM, Waitman Gobble wrote:
>>
>> When I set Content-Type header to multipart/form-data and add data to
>> CURLOPT_POSTFIELDS it seems to hang. I thought maybe proxy issue but
>> tried with/without.
>> 1) If sending simple string like a=foo&j=boo then there isn't an issue
>> 2) If I don't set Content-Length then it doesn't hang, makes the post.
>> However receiving side doesn't get data (content length 172 but should
>> be 134610
>>
>> Thanks for any help or pointers.
>>
>>
>> system,
>>
>> FreeBSD ob4.cloudqx.com 10.2-RELEASE-p9 FreeBSD 10.2-RELEASE-p9 #0:
>>
>> curl-7.47.0 from ports
>>
>>
>> #include <iostream>
>> #include <fstream>
>> #include <string>
>> #include <curl/curl.h>
>>
>> using namespace std;
>>
>> int main(void) {
>>
>> CURL *conn = NULL;
>> curl_global_init(CURL_GLOBAL_DEFAULT);
>>
>> conn = curl_easy_init();
>> static char errorBuffer[CURL_ERROR_SIZE];
>>
>> curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer);
>> //curl_easy_setopt(conn, CURLOPT_URL,
>> "http://wp.amodaco.com/filepost.php");
>> curl_easy_setopt(conn, CURLOPT_HEADER, 1L);
>> //curl_easy_setopt(conn, CURLOPT_PROXY, "http://127.0.0.1");
>> //curl_easy_setopt(conn, CURLOPT_PROXYPORT, 3128);
>>
>> curl_easy_setopt(conn, CURLOPT_URL,
>> "https://hub.zilla.tech/filepost.php");
>>
>> char* post_string;
>> int post_size;
>> ifstream file;
>> file.open("/c/nginx/0/11/0000000110",ios_base::binary);
>> //file.open("/c/nginx/7/10/0000000107",ios_base::binary);
>> file.seekg(0,ios::end);
>> post_size = file.tellg();
>> file.seekg(0,ios::beg);
>> post_string = new char[post_size];
>> file.read(post_string,post_size);
>> file.close();
>>
>> struct curl_slist *chunk = NULL;
>> chunk = curl_slist_append(chunk, "Content-Type: multipart/form-data;
>> boundary=-----------------------------84927149120355803091994092429");
>> std::string cl = "Content-Length: " + std::to_string(post_size);
>> chunk = curl_slist_append(chunk, cl.c_str());
>> curl_easy_setopt(conn, CURLOPT_POSTFIELDS, post_string);
>> curl_easy_setopt(conn, CURLOPT_HTTPHEADER, chunk);
>> cout << "before perform\r\n";
>> curl_easy_perform(conn);
>> curl_easy_cleanup(conn);
>> cout << "finis\r\n";
>> cout << cl << "\r\n";
>>
>> return(0);
>> }
>>
>
> Don't set those headers and if you want to do multipart don't use
> CURLOPT_POSTFIELDS, use CURLOPT_HTTPPOST [1] instead. Look at the EXAMPLE
> section it probably does what you need. Also review curl_formadd [2], If you
> have a particularly large file you'll need to use CURLFORM_STREAM and
> CURLOPT_READFUNCTION instead of loading the entire thing in memory.
>
> struct curl_httppost *formpost = NULL;
> struct curl_httppost *lastptr = NULL;
>
> <curl_formadd calls>
>
> curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
>
>
> As an aside, if you don't want multipart and you use CURLOPT_POSTFIELDS and
> pass it binary data set the size using CURLOPT_POSTFIELDSIZE [3] or
> CURLOPT_POSTFIELDSIZE_LARGE [4] and make sure you use exactly the type
> specified, for example:
>
> curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)post_size);
> or
> curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)post_size);
>
>
> [1]: https://curl.haxx.se/libcurl/c/CURLOPT_HTTPPOST.html
> [2]: https://curl.haxx.se/libcurl/c/curl_formadd.html
> [3]: https://curl.haxx.se/libcurl/c/CURLOPT_POSTFIELDSIZE.html
> [4]: https://curl.haxx.se/libcurl/c/CURLOPT_POSTFIELDSIZE_LARGE.html
>
>
>
> -------------------------------------------------------------------
> List admin: https://cool.haxx.se/list/listinfo/curl-library
> Etiquette: https://curl.haxx.se/mail/etiquette.html

Thanks for the replies, I will read through them and figure it out. I
really appreciate it.
I didn't post the entire file.

One thing I think the problem is in lib/http.c

      else if(data->set.postfields)
        expectsend = (curl_off_t)strlen(data->set.postfields);

strlen is wrong, the binary data has a character that cuts it off at
byte 172, the string is actually much bigger.

The documentation states that curl will use strlen if POSTFIELDSIZE is
not provided. But it looks like it's using strlen anyway.. :(
I'm guessing that' why it's sitting there until the end of time?

using the form struct doesn't look like it will help. I don't see how
to put "already" formatted data into the struct.. Basically I'd have
to regurgitate the data and break it into objects and feed back into
the form api, which seems not so good. But perhaps I'm mistaken.

-- 
Waitman Gobble
Los Altos California USA
650-900-8557
-------------------------------------------------------------------
List admin: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:  https://curl.haxx.se/mail/etiquette.html
Received on 2016-03-07