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:21:19 -0800

On Mon, Mar 7, 2016 at 12:10 AM, Waitman Gobble <gobble.wa_at_gmail.com> wrote:
> 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

example:

...
post_size = ftell(fp);
rewind(fp);
post_string = (char *)malloc((post_size+1)*sizeof(char));
size_t checklen = fread(post_string, 1, post_size, fp);
fclose(fp);

cout << "check len " << checklen << " post size " << post_size << " strlen " <<
(long)strlen(post_string) << "\r\n";

check len 134610 post size 134610 strlen 172

-- 
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