Skip to content

Instantly share code, notes, and snippets.

@carlalexander
Last active August 13, 2021 00:40
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save carlalexander/c779b473f62dcd1a4ca26fcaa637ec59 to your computer and use it in GitHub Desktop.
Save carlalexander/c779b473f62dcd1a4ca26fcaa637ec59 to your computer and use it in GitHub Desktop.
WordPress "Expect" header fix
<?php
/**
* By default, cURL sends the "Expect" header all the time which severely impacts
* performance. Instead, we'll send it if the body is larger than 1 mb like
* Guzzle does.
*/
function add_expect_header(array $arguments)
{
$arguments['headers']['expect'] = '';
if (is_array($arguments['body'])) {
$bytesize = 0;
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arguments['body']));
foreach ($iterator as $datum) {
$bytesize += strlen((string) $datum);
if ($bytesize >= 1048576) {
$arguments['headers']['expect'] = '100-Continue';
break;
}
}
} elseif (!empty($arguments['body']) && strlen((string) $arguments['body']) > 1048576) {
$arguments['headers']['expect'] = '100-Continue';
}
return $arguments;
}
add_filter('http_request_args', 'add_expect_header');
@carlalexander
Copy link
Author

carlalexander commented Mar 11, 2021

@nawawi you're right. I just put assumed it was always a string. I think something like this would work:

function add_expect_header(array $arguments)
{
    $body = $arguments['body']

    if (is_array($body)) {
        $body = implode('', $body);
    }

    $arguments['headers']['expect'] = !empty($body) && strlen($body) > 1048576 ? '100-Continue' : '';
    
    return $arguments;
}

@nawawi
Copy link

nawawi commented Mar 11, 2021

@carlalexander thanks!

@WpSpeedDoctor
Copy link

Hi Carl,
sorry for a noob question but can you describe what kind of website would benefit from your code? Where would I need to look to measure of the impact when I implement it? Or what kind of plugins or functions creates the problem your code solve?
Thank you very much!

@carlalexander
Copy link
Author

@WpSpeedDoctor Any code that uses the HTTP API to make requests can benefit from this change. You could measure the impact with a plugin like Query Monitor that tracks how long HTTP requests take. It's not guaranteed to make a difference, but the impact is either "no change from before" or a "significant reduction in time".

If you want to read more about it, there's a thread that discusses the issue on the cURL mailing list.

@indysigner
Copy link

Will it be enough to put this into a Child theme’s function.php or does this need to go into the root folder? Sorry if this question is too noob-ish, @carlalexander. Thanks!

@danieliser
Copy link

@carlalexander came here to report the body being an array issue, you might want to take your follow up code and make an official revision to this gist.

Also the first line in that updated version is missing a colon ;

And I think the time savings on the wp-admin/update-core.php page alone could be worth the addition.

@nawawi
Copy link

nawawi commented Jul 3, 2021

Hi, this should fix the body being array issue:

function add_expect_header(array $arguments)
{
    $body = $arguments['body'];

    if (is_array($body) || is_object($body)) {
        $body = json_encode($body);
    }

    $arguments['headers']['expect'] = !empty($body) && strlen($body) > 1048576 ? '100-Continue' : '';
    
    return $arguments;
}

@carlalexander
Copy link
Author

@indysigner sorry I just saw this now. I missed your notification. functions.php should be fine.

@danieliser @nawawi Yeah, there were a few issues with the code when developing a patch for core. I've updated the gist with the core patch.

@carlalexander
Copy link
Author

FYI for anyone tracking this issue. I worked on core on a fix here. I think it'll be live once WordPress 5.8 lands. It's not in as of 5.7.2.

@nawawi
Copy link

nawawi commented Jul 4, 2021

@carlalexander noted with thanks.

@Lolosan
Copy link

Lolosan commented Aug 4, 2021

It works great, but i still get "Array to string conversion", on this line:

$body = $arguments['body'];

    if ( is_array( $body ) )
	{
        $body = implode('', $body);  // not always, but sometimes i get "Array to string conversion" notice
    }

I'm not yet ready for WP 5.8, since big changes in widgets and my woocommerce plugins, etc

@carlalexander
Copy link
Author

@Lolosan do you still get it with the updated code?

@Lolosan
Copy link

Lolosan commented Aug 12, 2021

@Lolosan do you still get it with the updated code?

Thank you for the updated code, I'm testing in a woocommerce site with heavy use of APIs and everything seems great

This fix already comes with WP5.8, right? No need to use it after?

@carlalexander
Copy link
Author

@Lolosan That's correct 😄

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