WordPress.org

Make WordPress Core

Opened 6 weeks ago

Closed 6 weeks ago

#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:

Description

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(strpos($url,$siteurl)===false){
			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:

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

curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,


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

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

curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
rewind($verbose);
$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
6 weeks 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 6 weeks ago by SergeyBiryukov (previous) (diff)

#2 @atrixminerva
6 weeks 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:

<?php
function mymodule_curl_before_request($curlhandle){
        session_write_close();
}
add_action( 'requests-curl.before_request','mymodule_curl_before_request', 9999 );

#3 @SergeyBiryukov
6 weeks 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.