wp_remote_post doesn’t work with more than 1024 bytes in the body

What I need

I’m working with a third-party API (for the intents of this question, it’s irrelevant which one) and need to send a POST request to an external service.

I’m trying to use wp_remote_post to achieve what I need, but there seems to be a limit to the amount of data it can send in its request body.

The issue I’m facing

It gets sent only if the body contains up to 1024 characters. One character more and the request (apparently) isn’t sent.

Debug

I’m trying to debug the issue using ngrok to listen for the POST requests at $url, and manually setting $body as a string of “bla bla bla (…)”. They only show up when $body contains 1024 or less chars. I don’t get a 5xx error or any other error message. In fact, is_wp_error( $response ) returns false.

However, if I use a tool such as Postman to generate a similar POST request outside WP with more than 1024 characters in its body, ngrok receives it just fine.


  • WP -> request body smaller than 1024 bytes -> ngrok = OK
  • WP -> request body bigger than 1024 bytes -> ngrok = ??
  • Postman -> request body smaller than 1024 bytes -> ngrok = OK
  • Postman -> request body bigger than 1024 bytes -> ngrok = OK

What I tried

  • Sending the same request from outside WordPress with more than 1024 bytes on its body: it works.
  • A brand new WordPress install with no plugins and a default theme (twentyseventeen): it doesn’t work.
  • Trying on a different PC, with the latest Fedora install, the latest Linux kernel, the latest Firefox version, the latest Docker version: didn’t work.

My setup

  • Fedora Linux 24 kernel 4.11.12-100.fc24.x86_64
  • Docker version 1.12.6, build 78d1802
  • WordPress 4.9.5 from the official Docker image for WordPress
  • Firefox 54
  • ngrok 2.2.8

All tests are being made on my local machine, with WordPress 4.9.5 running inside a Docker container with the default WordPress image, and it uses the unmodified default configuration, except for the following custom php ini lines:

file_uploads = On
memory_limit = 64M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 600

The code

  $response = wp_remote_post( $url,
    array(
      'timeout' => 60,
      'redirection' => 5,
      'blocking' => true,
      'headers' => array(
        'Content-Type' => 'application/json',
      ),
      'body' => 'bla bla (...)' // fails if larger than 1024
    )
  );

  if ( is_wp_error( $response ) ) {
    $error_message = $response->get_error_message();
    echo "Something went wrong: $error_message";
  } else { echo "Request sent"; }

1 Answer
1

If you happen to be using the CURL transport, then it sometimes has minor problems sending POST requests greater than 1024 characters. More info here:

https://stackoverflow.com/questions/463144/php-http-post-fails-when-curl-data-1024

The fix suggested there is to send an empty Expect: header. You can do this by modifying your code thusly:

$response = wp_remote_post( $url,
    array(
      'timeout' => 60,
      'redirection' => 5,
      'blocking' => true,
      'headers' => array(
        'Content-Type' => 'application/json',
        'Expect' => '',
      ),
      'body' => 'bla bla (...)' // fails if larger than 1024
    )
  );

Edit: more info:

Some versions of curl and PHP, when you put in more than 1024 characters in the body, will send the headers first and then an “Expect: 100-continue” header. A webserver receiving this then should respond with a 100 Continue status for the client to continue to send the rest of the body.

If you’re using a real webserver, then it will send that response to receive the rest of the message. Some older webservers did not do this, thus the given workaround in that previous question.

I don’t know what ngrok is, but I’m betting it is not responding like a normal webserver here. Without that server saying to continue the POST, curl waits for it to do so. It times out eventually.

Leave a Comment