New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs are not clear about zero-byte POST #862

Closed
safinaskar opened this Issue Jun 6, 2016 · 8 comments

Comments

Projects
None yet
3 participants
@safinaskar
Contributor

safinaskar commented Jun 6, 2016

I cannot understand from online docs at https://curl.haxx.se/libcurl/c/ how to do zero-byte POST. It seems docs should be fixed. Is the following code ok?

curl_global_init (CURL_GLOBAL_ALL);
CURL *curl_handle = curl_easy_init ();
curl_easy_setopt (curl_handle, CURLOPT_URL, "http://example.com");
curl_easy_setopt (curl_handle, CURLOPT_POSTFIELDSIZE, 0L);
CURLcode code = curl_easy_perform (curl_handle);

Or I should also set CURLOPT_POST or CURLOPT_POSTFIELDS?
Is the following code ok? Does it really perform zero-byte POST?

curl_global_init (CURL_GLOBAL_ALL);
CURL *curl_handle = curl_easy_init ();
curl_easy_setopt (curl_handle, CURLOPT_URL, "http://example.com");
curl_easy_setopt (curl_handle, CURLOPT_POSTFIELDS, NULL); // is this line ok???
curl_easy_setopt (curl_handle, CURLOPT_POSTFIELDSIZE, 0L);
CURLcode code = curl_easy_perform (curl_handle);

@bagder bagder added the HTTP label Jun 6, 2016

@bagder

This comment has been minimized.

Show comment
Hide comment
@bagder

bagder Jun 6, 2016

Member

The CURLOPT_POSTFIELDS man page states:

If you want to do a zero-byte POST, you need to set CURLOPT_POSTFIELDSIZE(3) explicitly to zero, as simply setting CURLOPT_POSTFIELDS(3) to NULL or "" just effectively disables the sending of the specified string. libcurl will instead assume that you'll send the POST data using the read callback!

Isn't that good enough?

Member

bagder commented Jun 6, 2016

The CURLOPT_POSTFIELDS man page states:

If you want to do a zero-byte POST, you need to set CURLOPT_POSTFIELDSIZE(3) explicitly to zero, as simply setting CURLOPT_POSTFIELDS(3) to NULL or "" just effectively disables the sending of the specified string. libcurl will instead assume that you'll send the POST data using the read callback!

Isn't that good enough?

@bagder bagder added the documentation label Jun 6, 2016

@jay

This comment has been minimized.

Show comment
Hide comment
@jay

jay Jun 7, 2016

Member

Or I should also set CURLOPT_POST or CURLOPT_POSTFIELDS?

Yes that's what you should do.

@bagder I think maybe it's lost in translation. How about:

If CURLOPT_POSTFIELDS(3) is set to "" or NULL, and CURLOPT_POSTFIELDSIZE(3) is set to 0, then libcurl will do a zero-byte POST. If CURLOPT_POSTFIELDS(3) is set to "" or NULL, and CURLOPT_POSTFIELDSIZE(3) is not set to 0, then libcurl will get the POST data from the read callback.

Member

jay commented Jun 7, 2016

Or I should also set CURLOPT_POST or CURLOPT_POSTFIELDS?

Yes that's what you should do.

@bagder I think maybe it's lost in translation. How about:

If CURLOPT_POSTFIELDS(3) is set to "" or NULL, and CURLOPT_POSTFIELDSIZE(3) is set to 0, then libcurl will do a zero-byte POST. If CURLOPT_POSTFIELDS(3) is set to "" or NULL, and CURLOPT_POSTFIELDSIZE(3) is not set to 0, then libcurl will get the POST data from the read callback.

@bagder

This comment has been minimized.

Show comment
Hide comment
@bagder

bagder Jun 7, 2016

Member

@safinaskar, you think @jay's version makes it clearer?

Member

bagder commented Jun 7, 2016

@safinaskar, you think @jay's version makes it clearer?

@safinaskar

This comment has been minimized.

Show comment
Hide comment
@safinaskar

safinaskar Jun 7, 2016

Contributor

Yes :)

Contributor

safinaskar commented Jun 7, 2016

Yes :)

@jay

This comment has been minimized.

Show comment
Hide comment
@jay

jay Jun 8, 2016

Member

I tried indenting so it isn't so repetitive, how about this:

If CURLOPT_POSTFIELDS(3) is set to "" or NULL, and:
    CURLOPT_POSTFIELDSIZE(3) is set to 0, then libcurl will do a zero-byte POST.
    CURLOPT_POSTFIELDSIZE(3) is \fInot\fP set to 0, then libcurl will get the POST data from the read callback.

screenshot:
capture

is that better or worse

Member

jay commented Jun 8, 2016

I tried indenting so it isn't so repetitive, how about this:

If CURLOPT_POSTFIELDS(3) is set to "" or NULL, and:
    CURLOPT_POSTFIELDSIZE(3) is set to 0, then libcurl will do a zero-byte POST.
    CURLOPT_POSTFIELDSIZE(3) is \fInot\fP set to 0, then libcurl will get the POST data from the read callback.

screenshot:
capture

is that better or worse

@jay

This comment has been minimized.

Show comment
Hide comment
@jay

jay Jun 10, 2016

Member

I looked at this again and it would be incorrect to say libcurl will get the POST data from the read callback when CURLOPT_POSTFIELDSIZE is not 0 (I was assuming it's the default, but not necessarily).

It is also incorrect to say it will get the POST data from the read callback when just CURLOPT_POSTFIELDS is set to an empty string, even though that's the way it's been documented since 5a6dcdc. I couldn't go all the way back to 7.17 but I went back to curl 7.21 and setting CURLOPT_POSTFIELDS to "" results in a zero byte POST.

So assuming somewhere between 7.17 and 7.21 there wasn't a behavior change, how about this:

diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3 b/docs/libcurl/opts/CURLOPT_
index f9f9ead..17ec2d7 100644
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
@@ -42,16 +42,15 @@ This POST is a normal application/x-www-form-urlencoded kind
 set that Content-Type by default when this option is used), which is commonly
 used by HTML forms. Change Content-Type with \fICURLOPT_HTTPHEADER(3)\fP.

-Using \fICURLOPT_POSTFIELDS(3)\fP implies \fICURLOPT_POST(3)\fP.
-
 You can use \fIcurl_easy_escape(3)\fP to url-encode your data, if necessary. It
 returns a pointer to an encoded string that can be passed as \fIpostdata\fP.

-If you want to do a zero-byte POST, you need to set
-\fICURLOPT_POSTFIELDSIZE(3)\fP explicitly to zero, as simply setting
-\fICURLOPT_POSTFIELDS(3)\fP to NULL or "" just effectively disables the
-sending of the specified string. libcurl will instead assume that you'll send
-the POST data using the read callback!
+Using \fICURLOPT_POSTFIELDS(3)\fP implies \fICURLOPT_POST(3)\fP.
+
+If \fICURLOPT_POSTFIELDS(3)\fP is explicitly set to NULL then libcurl will get
+the POST data from the read callback. If you want to send a zero-byte POST set
+\fICURLOPT_POSTFIELDS(3)\fP to an empty string, or set \fICURLOPT_POST(3)\fP to
+1 and \fICURLOPT_POSTFIELDSIZE(3)\fP to 0.

 Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
 You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
Member

jay commented Jun 10, 2016

I looked at this again and it would be incorrect to say libcurl will get the POST data from the read callback when CURLOPT_POSTFIELDSIZE is not 0 (I was assuming it's the default, but not necessarily).

It is also incorrect to say it will get the POST data from the read callback when just CURLOPT_POSTFIELDS is set to an empty string, even though that's the way it's been documented since 5a6dcdc. I couldn't go all the way back to 7.17 but I went back to curl 7.21 and setting CURLOPT_POSTFIELDS to "" results in a zero byte POST.

So assuming somewhere between 7.17 and 7.21 there wasn't a behavior change, how about this:

diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3 b/docs/libcurl/opts/CURLOPT_
index f9f9ead..17ec2d7 100644
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
@@ -42,16 +42,15 @@ This POST is a normal application/x-www-form-urlencoded kind
 set that Content-Type by default when this option is used), which is commonly
 used by HTML forms. Change Content-Type with \fICURLOPT_HTTPHEADER(3)\fP.

-Using \fICURLOPT_POSTFIELDS(3)\fP implies \fICURLOPT_POST(3)\fP.
-
 You can use \fIcurl_easy_escape(3)\fP to url-encode your data, if necessary. It
 returns a pointer to an encoded string that can be passed as \fIpostdata\fP.

-If you want to do a zero-byte POST, you need to set
-\fICURLOPT_POSTFIELDSIZE(3)\fP explicitly to zero, as simply setting
-\fICURLOPT_POSTFIELDS(3)\fP to NULL or "" just effectively disables the
-sending of the specified string. libcurl will instead assume that you'll send
-the POST data using the read callback!
+Using \fICURLOPT_POSTFIELDS(3)\fP implies \fICURLOPT_POST(3)\fP.
+
+If \fICURLOPT_POSTFIELDS(3)\fP is explicitly set to NULL then libcurl will get
+the POST data from the read callback. If you want to send a zero-byte POST set
+\fICURLOPT_POSTFIELDS(3)\fP to an empty string, or set \fICURLOPT_POST(3)\fP to
+1 and \fICURLOPT_POSTFIELDSIZE(3)\fP to 0.

 Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
 You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
@bagder

This comment has been minimized.

Show comment
Hide comment
@bagder

bagder Jun 11, 2016

Member

Very good digging and research! 👍

Member

bagder commented Jun 11, 2016

Very good digging and research! 👍

jay added a commit that referenced this issue Jun 11, 2016

CURLOPT_POSTFIELDS.3: Clarify what happens when set empty
When CURLOPT_POSTFIELDS is set to an empty string libcurl will send a
zero-byte POST. Prior to this change it was documented as sending data
from the read callback.

This also changes the wording of what happens when empty or NULL so that
it's hopefully easier to understand for people whose primary language
isn't English.

Bug: #862
Reported-by: Askar Safin
@jay

This comment has been minimized.

Show comment
Hide comment
@jay

jay Jun 11, 2016

Member

Tested back to 7.17 and same thing, so this has landed in f77dfbc. Thanks

Member

jay commented Jun 11, 2016

Tested back to 7.17 and same thing, so this has landed in f77dfbc. Thanks

@jay jay closed this Jun 11, 2016

@lock lock bot locked as resolved and limited conversation to collaborators May 7, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.