curl / Mailing Lists / curl-library / Single Mail


Improving form post API

From: Andrew <>
Date: Tue, 20 Jun 2017 14:15:01 -0700


In the user survey this year I made a comment about curl_formadd being a
pain for bindings to languages that don't allow variadic foreign functions.

I commented on Daniel's blog post about the survey that I'd like to help
move this forward. But since C is still a "read only" language for me,
I'm not sure how much help I can be except to share my perspective as a
developer and user of the language binding I was referring to

It seems I'm not alone in thinking that this function is problematic:

Daniel identifies three issues with the current API:
  * complicated (multitple varargs, several ways to do the same thing)
  * error-prone (due to the above)
  * the use of the public struct makes it hard to change - and yet
    hardly any users actually create the linked list of headers

He suggests a new API where the form is an opaque handle that you get
from curl_form_init, and then you call curl_form_addpart on the form
handle to get a handle to a new part. Parts are populated with
curl_form_set_name and curl_form_set_data.

I really like the idea of using an opaque handle instead of a pointer to
a list of structures, and this is basically how I already present it in
my binding. I also agree with the notion that CURLFORM_PTRCONTENTS,
CURLFORM_PTRNAME, and CURLFORM_ARRAY should be deprecated. For
small/non-file form parts using a pointer for the contents doesn't seem
obviously useful, and a pointer for the name even less so. My binding
doesn't even expose these features to the user. It also seems like
encoding several CURLFORM_FILE in the same form part might be a problem
if curl_form_set_data overwrites the previous data.

Seemingly missing in the proposal are equivalents for CURLFORM_STREAM
and CURLFORM_BUFFERPTR. If curl_form_set_data were to always copy the
data then I don't see how these modes could be made to work. Perhaps if
instead of separate functions for the name and data there were a single
curl_form_setopt function? e.g.

  curl_form_setopt(part1, CURLFORM_COPYNAME, "name", 4);
  curl_form_setopt(part1, CURLFORM_BUFFERPTR, someptr, 6);
  curl_form_setopt(part2, CURLFORM_COPYNAME, "shoesize", 8);
  curl_form_setopt(part2, CURLFORM_STREAM, usercontext, -1);

This would also mean that you don't need separate functions for

Also a curl_form_setopt function could be made to work with both
individual parts or the overall form depending on whether the form or
the part are passed in as the first argument (though this might be

Thanks for reading,
Andrew Lambert
Received on 2017-06-20