Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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');
@Luehrsen

This comment has been minimized.

Copy link

@Luehrsen Luehrsen commented Mar 11, 2021

This just shaved a good 100-200ms from a API heavy function in my WP.

Very well done, good find!

@nawawi

This comment has been minimized.

Copy link

@nawawi nawawi commented Mar 11, 2021

$arguments['body'] might be an array, php will throw warning -> PHP Warning: strlen() expects parameter 1 to be string, array given

@carlalexander

This comment has been minimized.

Copy link
Owner Author

@carlalexander 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

This comment has been minimized.

Copy link

@nawawi nawawi commented Mar 11, 2021

@carlalexander thanks!

@WpSpeedDoctor

This comment has been minimized.

Copy link

@WpSpeedDoctor WpSpeedDoctor commented Mar 12, 2021

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

This comment has been minimized.

Copy link
Owner Author

@carlalexander carlalexander commented Mar 12, 2021

@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

This comment has been minimized.

Copy link

@indysigner indysigner commented Mar 31, 2021

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

This comment has been minimized.

Copy link

@danieliser danieliser commented Jul 3, 2021

@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

This comment has been minimized.

Copy link

@nawawi 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

This comment has been minimized.

Copy link
Owner Author

@carlalexander carlalexander commented Jul 3, 2021

@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

This comment has been minimized.

Copy link
Owner Author

@carlalexander carlalexander commented Jul 3, 2021

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

This comment has been minimized.

Copy link

@nawawi nawawi commented Jul 4, 2021

@carlalexander noted with thanks.

@Lolosan

This comment has been minimized.

Copy link

@Lolosan 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

This comment has been minimized.

Copy link
Owner Author

@carlalexander carlalexander commented Aug 9, 2021

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

@Lolosan

This comment has been minimized.

Copy link

@Lolosan 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

This comment has been minimized.

Copy link
Owner Author

@carlalexander carlalexander commented Aug 13, 2021

@Lolosan That's correct 😄

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