Make WordPress Core

#50491 closed defect (bug) (invalid)

Loopback request fails if headers set in curl

Reported by: atrixminerva Owned by:
Milestone: Priority: normal
Severity: normal Version: 5.4.2
Component: HTTP API Keywords:
Focuses: Cc:


Spent 8 hours trying to find out why a test php curl request worked to loop back but the request failed if I used the popular site health plugin.

Changing this on line 379 of wp-includes/Requests/Transport/cURL.php fixed the issue and didn't seem to have any downsides to anything else it did.

			if (!empty($headers)) {
				curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers);

Changed to :

		$siteurl = get_site_url();
			if (!empty($headers)) {
				curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers);

I checked the headers variable and this is what it contained:

    [0] => Cache-Control: no-cache
    [1] => Cookie: wordpress_sec_fcf53b9c04d35e6528379f0ab7904d42=zUXwDfi7MGOAOA7HvHTxyZr06Qwp21241|1593375532|fosnAUIhzmSJXO85300mN7i3MtvYBZQyvussFLPl6yr|cc8aa8b11a625ec69ea4fdc079196feeaeeef427f6966d3737fae6d935e1572d; mailchimp_landing_site=https://woodev.wanaryd.com/wp-json/jetpack/v4/jitm?message_path=wp%3Atoplevel_page_PHPInfoer%3Aadmin_notices&query=page%253DPHPInfoer&full_jp_logo_exists=false&_wpnonce=a61c75d0ce; tk_or=""; tk_lr=""; ksiq5s96zvwo3vdb13nr8wwyvm2latj8z9irssyug22z6cnc3ia49otkmcao3m7l=1; wp-settings-140212=libraryContent=browse&editor=tinymce&mfold=o; wp-settings-time-140212=1588867823; wp_woocommerce_session_fcf53b9c04d35e6528379f0ab7904d42=140212||1593368136||1593364536||c28c6af25f6852e9c0e70a30ae60e927; woocommerce_items_in_cart=1; woocommerce_cart_hash=b8d25f4608d58cc3309f638e78f7480b; wordpress_test_cookie=WP Cookie check; wordpress_logged_in_fcf53b9c04d35e6528379f0ab7904d42=zUXwDfi7MGOAOA7HvHTxyZr06Qwp21241|1593375532|fosnAUIhzmSJXO85300mN7i3MtvYBZQyvussFLPl6yr|ea7afbf534177d515c60bd01b27e7a3669b77e25f492308bba5f9b3304763959; PHPSESSID=74aa2k81r2on9p9c6l5c49ko20; tk_ai=woo:DFEGOiVS6CNRIsr2gbYjq4E4; tk_tc=RyXKBSetMYuJlTSJ; mst-cache-warmer-track=1593285439509; form_key=PSaMgFOYHz0KUZIa
    [2] => Connection: close

If the headers are set in curl it gives this error instead of completing the request successfully:

cURL error 28: Operation timed out after 10001 milliseconds with 0 out of -1 bytes received

Which makes the request fail and loopbacks fail.

Here is a simple CURL test I setup that works to make sure curl could connect and it wasn't something set falsely:

$url = "https://site.com/wp-admin";
$ch = curl_init();

curl_setopt_array($ch, [
    CURLOPT_URL => $url,

     * Specify debug option
    CURLOPT_VERBOSE => true,
#curl_setopt($this->handle, CURLOPT_HEADER, false);

$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);

$info = curl_getinfo($ch);
$verboseLog = stream_get_contents($verbose);

echo "Verbose information:\n<pre>", htmlspecialchars($verboseLog), print_r($info), "</pre>\n";

This always worked without fail.

Change History (3)

#1 @SergeyBiryukov
19 months ago

  • Keywords close added

Hi there, welcome to WordPress Trac! Thanks for the report.

As far as I know, this does not happen on a clean WordPress install, only if a plugin or theme starts a PHP session with a session_start() function call. WordPress core itself does not use PHP sessions.

A solution would be to close the session by session_write_close() before making any HTTP requests.

See #47320 and #43358 for more details.

WordPress 5.5 will have a Site Health test for any active PHP session as a possible reason for HTTP requests timing out, added in [47585] / #47320.

Note that Requests is an external library, so changing it in the proposed way is not a viable option, any suggestions would need to be submitted upstream.

Last edited 19 months ago by SergeyBiryukov (previous) (diff)

#2 @atrixminerva
19 months ago

Confirming session_write_close() fixes the issue if done before the call, if there are headers being sent.

This code can fix that without modifying anything in the library itself. Not sure it's useful for fixing it in the end but it's at least much cleaner:

function mymodule_curl_before_request($curlhandle){
add_action( 'requests-curl.before_request','mymodule_curl_before_request', 9999 );

#3 @SergeyBiryukov
19 months ago

  • Keywords close removed
  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed

Thanks for the follow-up!

Closing, as this is not an issue with WordPress core or the Requests library, but rather a limitation of PHP sessions.

Note: See TracTickets for help on using tickets.