Make WordPress Core


Ignore:
Timestamp:
05/11/2021 07:40:41 PM (5 years ago)
Author:
desrosj
Message:

External Libraries: Update the Requests library to version 1.8.0.

While some of the changes in the 1.8.0 release have already been copied to WordPress Core in earlier releases (see [38727], [46258], [47902] and [49382]), this release contains additional improvements, including:

  • A significant performance fix when using cURL.
  • Improved compliance with RFC2616.

The library has also been moved under the WordPress project’s GitHub organization and can now be found at ​https://github.com/WordPress/Requests.

Props jrf, dd32, rmccue, justinahinon, netweb, schlessera, TimothyBJacobs, soulseekah, ozh, skithund, carlalexander, travisnorthcutt, desrosj.
Fixes #53101.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/Requests/Transport/cURL.php

    r46586 r50842  
    3939
    4040        /**
    41          * Version string
    42          *
    43          * @var long
     41         * cURL version number
     42         *
     43         * @var int
    4444         */
    4545        public $version;
    … …  
    9191         */
    9292        public function __construct() {
    93                 $curl = curl_version();
     93                $curl          = curl_version();
    9494                $this->version = $curl['version_number'];
    95                 $this->handle = curl_init();
     95                $this->handle  = curl_init();
    9696
    9797                curl_setopt($this->handle, CURLOPT_HEADER, false);
    … …  
    101101                }
    102102                if (defined('CURLOPT_PROTOCOLS')) {
     103                        // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_protocolsFound
    103104                        curl_setopt($this->handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
    104105                }
    105106                if (defined('CURLOPT_REDIR_PROTOCOLS')) {
     107                        // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_redir_protocolsFound
    106108                        curl_setopt($this->handle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
    107109                }
    … …  
    139141                }
    140142
    141                 $this->response_data = '';
    142                 $this->response_bytes = 0;
     143                $this->response_data       = '';
     144                $this->response_bytes      = 0;
    143145                $this->response_byte_limit = false;
    144146                if ($options['max_bytes'] !== false) {
    … …  
    169171                        curl_setopt($this->handle, CURLOPT_ENCODING, 'none');
    170172
    171                         $this->response_data = '';
     173                        $this->response_data  = '';
    172174                        $this->response_bytes = 0;
    173175                        curl_exec($this->handle);
    … …  
    200202                $multihandle = curl_multi_init();
    201203                $subrequests = array();
    202                 $subhandles = array();
     204                $subhandles  = array();
    203205
    204206                $class = get_class($this);
    205207                foreach ($requests as $id => $request) {
    206208                        $subrequests[$id] = new $class();
    207                         $subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']);
     209                        $subhandles[$id]  = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']);
    208210                        $request['options']['hooks']->dispatch('curl.before_multi_add', array(&$subhandles[$id]));
    209211                        curl_multi_add_handle($multihandle, $subhandles[$id]);
    210212                }
    211213
    212                 $completed = 0;
    213                 $responses = array();
     214                $completed       = 0;
     215                $responses       = array();
     216                $subrequestcount = count($subrequests);
    214217
    215218                $request['options']['hooks']->dispatch('curl.before_multi_exec', array(&$multihandle));
    216219
    217220                do {
    218                         $active = false;
     221                        $active = 0;
    219222
    220223                        do {
    … …  
    236239                        foreach ($to_process as $key => $done) {
    237240                                $options = $requests[$key]['options'];
    238                                 if (CURLE_OK !== $done['result']) {
     241                                if ($done['result'] !== CURLE_OK) {
    239242                                        //get error string for handle.
    240                                         $reason = curl_error($done['handle']);
    241                                         $exception = new Requests_Exception_Transport_cURL(
    242                                                                         $reason,
    243                                                                         Requests_Exception_Transport_cURL::EASY,
    244                                                                         $done['handle'],
    245                                                                         $done['result']
    246                                                                 );
     243                                        $reason          = curl_error($done['handle']);
     244                                        $exception       = new Requests_Exception_Transport_cURL(
     245                                                $reason,
     246                                                Requests_Exception_Transport_cURL::EASY,
     247                                                $done['handle'],
     248                                                $done['result']
     249                                        );
    247250                                        $responses[$key] = $exception;
    248251                                        $options['hooks']->dispatch('transport.internal.parse_error', array(&$responses[$key], $requests[$key]));
    … …  
    263266                        }
    264267                }
    265                 while ($active || $completed < count($subrequests));
     268                while ($active || $completed < $subrequestcount);
    266269
    267270                $request['options']['hooks']->dispatch('curl.after_multi_exec', array(&$multihandle));
    … …  
    288291                }
    289292
    290                 $this->response_data = '';
    291                 $this->response_bytes = 0;
     293                $this->response_data       = '';
     294                $this->response_bytes      = 0;
    292295                $this->response_byte_limit = false;
    293296                if ($options['max_bytes'] !== false) {
    … …  
    311314
    312315                // Force closing the connection for old versions of cURL (<7.22).
    313                 if ( ! isset( $headers['Connection'] ) ) {
     316                if (!isset($headers['Connection'])) {
    314317                        $headers['Connection'] = 'close';
     318                }
     319
     320                /**
     321                 * Add "Expect" header.
     322                 *
     323                 * By default, cURL adds a "Expect: 100-Continue" to most requests. This header can
     324                 * add as much as a second to the time it takes for cURL to perform a request. To
     325                 * prevent this, we need to set an empty "Expect" header. To match the behaviour of
     326                 * Guzzle, we'll add the empty header to requests that are smaller than 1 MB and use
     327                 * HTTP/1.1.
     328                 *
     329                 * https://curl.se/mail/lib-2017-07/0013.html
     330                 */
     331                if (!isset($headers['Expect']) && $options['protocol_version'] === 1.1) {
     332                        $headers['Expect'] = $this->get_expect_header($data);
    315333                }
    316334
    … …  
    321339
    322340                        if ($data_format === 'query') {
    323                                 $url = self::format_get($url, $data);
     341                                $url  = self::format_get($url, $data);
    324342                                $data = '';
    325343                        }
    … …  
    364382                }
    365383                else {
     384                        // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_timeout_msFound
    366385                        curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000));
    367386                }
    … …  
    371390                }
    372391                else {
     392                        // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_connecttimeout_msFound
    373393                        curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000));
    374394                }
    … …  
    386406                }
    387407
    388                 if (true === $options['blocking']) {
    389                         curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, array(&$this, 'stream_headers'));
    390                         curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, array(&$this, 'stream_body'));
     408                if ($options['blocking'] === true) {
     409                        curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, array($this, 'stream_headers'));
     410                        curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, array($this, 'stream_body'));
    391411                        curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE);
    392412                }
    … …  
    398418         * @param string $response Response data from the body
    399419         * @param array $options Request options
    400          * @return string HTTP response data including headers
     420         * @return string|false HTTP response data including headers. False if non-blocking.
     421         * @throws Requests_Exception
    401422         */
    402423        public function process_response($response, $options) {
    … …  
    406427                        return false;
    407428                }
    408                 if ($options['filename'] !== false) {
     429                if ($options['filename'] !== false && $this->stream_handle) {
    409430                        fclose($this->stream_handle);
    410431                        $this->headers = trim($this->headers);
    … …  
    440461                // (We may want to keep this somewhere just in case)
    441462                if ($this->done_headers) {
    442                         $this->headers = '';
     463                        $this->headers      = '';
    443464                        $this->done_headers = false;
    444465                }
    … …  
    474495                                // Limit the length
    475496                                $limited_length = ($this->response_byte_limit - $this->response_bytes);
    476                                 $data = substr($data, 0, $limited_length);
     497                                $data           = substr($data, 0, $limited_length);
    477498                        }
    478499                }
    … …  
    498519        protected static function format_get($url, $data) {
    499520                if (!empty($data)) {
     521                        $query     = '';
    500522                        $url_parts = parse_url($url);
    501523                        if (empty($url_parts['query'])) {
    502                                 $query = $url_parts['query'] = '';
     524                                $url_parts['query'] = '';
    503525                        }
    504526                        else {
    … …  
    507529
    508530                        $query .= '&' . http_build_query($data, null, '&');
    509                         $query = trim($query, '&');
     531                        $query  = trim($query, '&');
    510532
    511533                        if (empty($url_parts['query'])) {
    … …  
    540562                return true;
    541563        }
     564
     565        /**
     566         * Get the correct "Expect" header for the given request data.
     567         *
     568         * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD.
     569         * @return string The "Expect" header.
     570         */
     571        protected function get_expect_header($data) {
     572                if (!is_array($data)) {
     573                        return strlen((string) $data) >= 1048576 ? '100-Continue' : '';
     574                }
     575
     576                $bytesize = 0;
     577                $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
     578
     579                foreach ($iterator as $datum) {
     580                        $bytesize += strlen((string) $datum);
     581
     582                        if ($bytesize >= 1048576) {
     583                                return '100-Continue';
     584                        }
     585                }
     586
     587                return '';
     588        }
    542589}
Note: See TracChangeset for help on using the changeset viewer.