Viewed   102 times

Note: solution at the end

If I attempt to do a HTTP POST of over 1024 characters, it fails. Why? Here is a minimal example:

recipient.php:

<?php
if (strlen(file_get_contents('php://input')) > 1000
    || strlen($HTTP_RAW_POST_DATA) > 1000) {
 echo "This was a triumph.";
}
?>

sender.php:

<?php
function try_to_post($char_count) {
 $url = 'http://gpx3quaa.joyent.us/test/recipient.php';
 $post_data = str_repeat('x', $char_count);
 $c = curl_init();
 curl_setopt_array($c,
                    array(  CURLOPT_URL => $url,
                            CURLOPT_HEADER => false,
                            CURLOPT_CONNECTTIMEOUT => 999,
                            CURLOPT_RETURNTRANSFER => true,
                            CURLOPT_POST => 1,
                            CURLOPT_POSTFIELDS => $post_data
                    )
 );
 $result = curl_exec($c);
 echo "{$result}n";
 curl_close($c);
}

for ($i=1020;$i<1030;$i++) {
 echo "Trying {$i} - ";
 try_to_post($i);
}
?>

output:

Trying 1020 - This was a triumph.
Trying 1021 - This was a triumph.
Trying 1022 - This was a triumph.
Trying 1023 - This was a triumph.
Trying 1024 - This was a triumph.
Trying 1025 - 
Trying 1026 - 
Trying 1027 - 
Trying 1028 - 
Trying 1029 - 

configuration:

PHP Version 5.2.6
libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3 libidn/1.8
lighttpd-1.4.19

Solution

Add the following option for cURL:

curl_setopt($ch,CURLOPT_HTTPHEADER,array("Expect:"));

The reason seems to be that any POST over 1024 character causes the "Expect: 100-continue" HTTP header to be sent, and Lighttpd 1.4.* does not support it. I found a ticket for it: http://redmine.lighttpd.net/issues/show/1017

They say it works in 1.5.

 Answers

3

You can convince PHP's curl backend to stop doing the 100-continue-thing by setting an explicit request header:

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

This way you can post a request however long you would ever want and curl will not do the dual phase post.

I've blogged about this nearly two years ago.

Monday, October 3, 2022
 
mivra
 
3

Change the order around:

header("Location: ..."); // The new resource URL
header('HTTP/1.1 201 Created');
header('Content-type: application/json; charset=utf-8');
echo $response;
exit;

Test:

# curl -i "http://localhost/projects/scratch/302.php"
HTTP/1.1 201 Created
Date: Sun, 29 Jan 2012 23:09:02 GMT
Server: Apache/2.2.17 (Win32) mod_ssl/2.2.17 OpenSSL/0.9.8o PHP/5.3.4 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.5
Location: ...
Content-Length: 0
Content-Type: application/json; charset=utf-8

Another way

Keep the original order, but force a 201. According to the PHP docs:

it also returns a REDIRECT (302) status code to the browser unless the 201 or a 3xx status code has already been set.

header('HTTP/1.1 201 Created', true, 201);
header("Location: ..."); // The new resource URL
header('Content-type: application/json; charset=utf-8');
echo $response;
exit;
Thursday, December 15, 2022
 
1

See also: How to post data in PHP using file_get_contents?

Basically you can use file_get_contents() and stream_context_create() for issuing a POST request. In your case:

$post = http_build_query(array(
    "username" => "user",
    "password" => "pw",
    "example" => "...",
));

$context = stream_context_create(array("http"=>array(
     "method" => "POST",
     "header" => "Content-Type: application/x-www-form-urlencodedrn" .
                 "Content-Length: ". strlen($post) . "rn",  
     "content" => $post,
))); 

$page = file_get_contents("http://example.com/login", false, $context);
Sunday, September 18, 2022
 
4

Multiple -d looks fine. The docs said -d name=daniel -d skill=lousy will generate name=daniel&skill=lousy

http://curl.haxx.se/docs/manpage.html#-d

So if you want send an array, you have to use the [] brackets.

-d name[]=peter -d name[]=paul -d name[]=mary

It looks like you can also use

-d "name[]=peter&name[]=paul&name=mary"
Thursday, October 27, 2022
 
juunas
 
2

Ah, simple mistake, I need to pass char * to curl_easy_setopt and not string. To fix this I've just used .c_str() like so:

CURL *curl = curl_easy_init();
_ASSERTE(curl);

string url = "http://127.0.0.1:8000/";

char *data = "mode=test";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
CURLcode res = curl_easy_perform(curl);

bool success = (res == CURLE_OK);

curl_easy_cleanup(curl);
Friday, August 12, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :