Curl --form with Zig std

I want to rewrite some old bash script in a portable Zig. The thing that is not obvious to me is how I can implement something like --form (-F) flag of curl. The actual call looks like this:

curl -m 30 -f -F "f1=@/my/file" -F "f2=arg2" -F "f3=arg3" http://example.com

-m and -f doesn’t look hard, the real issue is -F. Note that there are forms with strings (=arg) and a form with a file (=@/my/file). I want to get a response from this call.

I’d like a solution that is as simple as possible, ideally with no dependencies (aside from std). Is it hard to implement?

Everything web-related is not my area of expertise, so any references that may improve my low-level fundamental understanding of this stuff are appreciated. I’ve skimmed through RFC 2388 (multipart/form-data), but looks like it requires a lot of prior knowledge to understand it.

By adding --trace-ascii output-file.txt in your curl command line, the body of the message that curl sends to server is recorded in output-file.txt. You can also use --trace-ascii - to send the output to your terminal standard output.

What you need to specify in the header are:

  • the Content-Type as multipart/form-data; boundary=RANDOM-BOUNDARY where RANDOM-BOUNDARY is a line separator that must not exist in the form data and as any line of the posted files.
  • the Content-Length as the total length in bytes of the message without header, including all the separators.

In the body each line is also separated by \r\n, the first and the last line must have RANDOM-BOUNDARY
For each form field (e.g. -F f2=arg2) you must have a part as:

Content-Disposition: form-data; name="f2"

arg2

and for file contents you must use:

Content-Disposition: form-data; name="f1"; filename="file"
Content-Type: text/plain

Contents of file

Each part must be separated by RANDOM-BOUNDARY.


See also: How do I post a file to a website?

3 Likes

It was really helpful, everything works now. curl --trace-ascii (as well as --trace) helped me to understand what’s happening behind the curtain.

It was noted in the linked thread, but I want to reiterate it (because I didn’t notice it right away). RANDOM-BOUNDARY in the body has to always have additional two dashes -- at the beginning. So, for example, for this content type

Content-Type: multipart/form-data; boundary=----eb542ed298bc07fa2f58d09191f02dbbffbaa477

(4 dashes) boundary line in the body has to be

------eb542ed298bc07fa2f58d09191f02dbbffbaa477

(6 dashes). The very last boundary has to have 2 additional dashes at the end.

------eb542ed298bc07fa2f58d09191f02dbbffbaa477--

Thank you!

2 Likes