Ticket #8622: 8622.4.diff

File 8622.4.diff, 11.1 KB (added by dd32, 2 years ago)

Heavy handed approach, Assumes fopen is gone(#13915) therefor Get/Post can be combined

  • wp-includes/class-http.php

     
    3838class WP_Http { 
    3939 
    4040        /** 
    41          * PHP4 style Constructor - Calls PHP5 Style Constructor 
    42          * 
    43          * @since 2.7.0 
    44          * @return WP_Http 
    45          */ 
    46         function WP_Http() { 
    47                 $this->__construct(); 
    48         } 
    49  
    50         /** 
    51          * PHP5 style Constructor - Set up available transport if not available. 
    52          * 
    53          * PHP4 does not have the 'self' keyword and since WordPress supports PHP4, the class needs to 
    54          * be used for the static call. The transport are set up to save time and will only be created 
    55          * once. This class can be created many times without having to go through the step of finding 
    56          * which transports are available. 
    57          * 
    58          * @since 2.7.0 
    59          * @return WP_Http 
    60          */ 
    61         function __construct() { 
    62                 WP_Http::_getTransport(); 
    63                 WP_Http::_postTransport(); 
    64         } 
    65  
    66         /** 
    67          * Tests the WordPress HTTP objects for an object to use and returns it. 
    68          * 
    69          * Tests all of the objects and returns the object that passes. Also caches that object to be 
    70          * used later. 
    71          * 
    72          * The order for the GET/HEAD requests are HTTP Extension, cURL, Streams, Fopen, and finally 
    73          * Fsockopen. fsockopen() is used last, because it has the most overhead in its implementation. 
    74          * There isn't any real way around it, since redirects have to be supported, much the same way 
    75          * the other transports also handle redirects. 
    76          * 
    77          * There are currently issues with "localhost" not resolving correctly with DNS. This may cause 
    78          * an error "failed to open stream: A connection attempt failed because the connected party did 
    79          * not properly respond after a period of time, or established connection failed because [the] 
    80          * connected host has failed to respond." 
    81          * 
    82          * @since 2.7.0 
    83          * @access private 
    84          * 
    85          * @param array $args Request args, default us an empty array 
    86          * @return object|null Null if no transports are available, HTTP transport object. 
    87          */ 
    88         function &_getTransport( $args = array() ) { 
    89                 static $working_transport, $blocking_transport, $nonblocking_transport; 
    90  
    91                 if ( is_null($working_transport) ) { 
    92                         if ( true === WP_Http_ExtHttp::test($args) ) { 
    93                                 $working_transport['exthttp'] = new WP_Http_ExtHttp(); 
    94                                 $blocking_transport[] = &$working_transport['exthttp']; 
    95                         } else if ( true === WP_Http_Curl::test($args) ) { 
    96                                 $working_transport['curl'] = new WP_Http_Curl(); 
    97                                 $blocking_transport[] = &$working_transport['curl']; 
    98                         } else if ( true === WP_Http_Streams::test($args) ) { 
    99                                 $working_transport['streams'] = new WP_Http_Streams(); 
    100                                 $blocking_transport[] = &$working_transport['streams']; 
    101                         } else if ( true === WP_Http_Fopen::test($args) ) { 
    102                                 $working_transport['fopen'] = new WP_Http_Fopen(); 
    103                                 $blocking_transport[] = &$working_transport['fopen']; 
    104                         } else if ( true === WP_Http_Fsockopen::test($args) ) { 
    105                                 $working_transport['fsockopen'] = new WP_Http_Fsockopen(); 
    106                                 $blocking_transport[] = &$working_transport['fsockopen']; 
    107                         } 
    108  
    109                         foreach ( array('curl', 'streams', 'fopen', 'fsockopen', 'exthttp') as $transport ) { 
    110                                 if ( isset($working_transport[$transport]) ) 
    111                                         $nonblocking_transport[] = &$working_transport[$transport]; 
    112                         } 
    113                 } 
    114  
    115                 do_action( 'http_transport_get_debug', $working_transport, $blocking_transport, $nonblocking_transport ); 
    116  
    117                 if ( isset($args['blocking']) && !$args['blocking'] ) 
    118                         return $nonblocking_transport; 
    119                 else 
    120                         return $blocking_transport; 
    121         } 
    122  
    123         /** 
    124          * Tests the WordPress HTTP objects for an object to use and returns it. 
    125          * 
    126          * Tests all of the objects and returns the object that passes. Also caches 
    127          * that object to be used later. This is for posting content to a URL and 
    128          * is used when there is a body. The plain Fopen Transport can not be used 
    129          * to send content, but the streams transport can. This is a limitation that 
    130          * is addressed here, by just not including that transport. 
    131          * 
    132          * @since 2.7.0 
    133          * @access private 
    134          * 
    135          * @param array $args Request args, default us an empty array 
    136          * @return object|null Null if no transports are available, HTTP transport object. 
    137          */ 
    138         function &_postTransport( $args = array() ) { 
    139                 static $working_transport, $blocking_transport, $nonblocking_transport; 
    140  
    141                 if ( is_null($working_transport) ) { 
    142                         if ( true === WP_Http_ExtHttp::test($args) ) { 
    143                                 $working_transport['exthttp'] = new WP_Http_ExtHttp(); 
    144                                 $blocking_transport[] = &$working_transport['exthttp']; 
    145                         } else if ( true === WP_Http_Curl::test($args) ) { 
    146                                 $working_transport['curl'] = new WP_Http_Curl(); 
    147                                 $blocking_transport[] = &$working_transport['curl']; 
    148                         } else if ( true === WP_Http_Streams::test($args) ) { 
    149                                 $working_transport['streams'] = new WP_Http_Streams(); 
    150                                 $blocking_transport[] = &$working_transport['streams']; 
    151                         } else if ( true === WP_Http_Fsockopen::test($args) ) { 
    152                                 $working_transport['fsockopen'] = new WP_Http_Fsockopen(); 
    153                                 $blocking_transport[] = &$working_transport['fsockopen']; 
    154                         } 
    155  
    156                         foreach ( array('curl', 'streams', 'fsockopen', 'exthttp') as $transport ) { 
    157                                 if ( isset($working_transport[$transport]) ) 
    158                                         $nonblocking_transport[] = &$working_transport[$transport]; 
    159                         } 
    160                 } 
    161  
    162                 do_action( 'http_transport_post_debug', $working_transport, $blocking_transport, $nonblocking_transport ); 
    163  
    164                 if ( isset($args['blocking']) && !$args['blocking'] ) 
    165                         return $nonblocking_transport; 
    166                 else 
    167                         return $blocking_transport; 
    168         } 
    169  
    170         /** 
    17141         * Send a HTTP request to a URI. 
    17242         * 
    17343         * The body and headers are part of the arguments. The 'body' argument is for the body and will 
     
    286156                        // header isn't already set. 
    287157                        if ( ($r['method'] == 'POST' || $r['method'] == 'PUT') && ! isset( $r['headers']['Content-Length'] ) ) 
    288158                                $r['headers']['Content-Length'] = 0; 
    289  
    290                         // The method is ambiguous, because we aren't talking about HTTP methods, the "get" in 
    291                         // this case is simply that we aren't sending any bodies and to get the transports that 
    292                         // don't support sending bodies along with those which do. 
    293                         $transports = WP_Http::_getTransport( $r ); 
    294159                } else { 
    295160                        if ( is_array( $r['body'] ) || is_object( $r['body'] ) ) { 
    296161                                if ( ! version_compare(phpversion(), '5.1.2', '>=') ) 
     
    303168 
    304169                        if ( ! isset( $r['headers']['Content-Length'] ) && ! isset( $r['headers']['content-length'] ) ) 
    305170                                $r['headers']['Content-Length'] = strlen( $r['body'] ); 
    306  
    307                         // The method is ambiguous, because we aren't talking about HTTP methods, the "post" in 
    308                         // this case is simply that we are sending HTTP body and to get the transports that do 
    309                         // support sending the body. Not all do, depending on the limitations of the PHP core 
    310                         // limitations. 
    311                         $transports = WP_Http::_postTransport( $r ); 
    312171                } 
    313172 
    314                 do_action( 'http_api_debug', $transports, 'transports_list' ); 
     173                return $this->_dispatch_request($url, $r); 
     174        } 
    315175 
    316                 $response = array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); 
    317                 foreach ( (array) $transports as $transport ) { 
    318                         $response = $transport->request( $url, $r ); 
     176        // Need to check the pass-by-reference stuff here to reduce the number of variable copies vs. references 
     177        // @TODO: Also, Docs. 
     178        function _dispatch_request($url, $r) { 
     179                static $transports; 
    319180 
    320                         do_action( 'http_api_debug', $response, 'response', get_class( $transport ) ); 
     181                $request_order = isset($r['blocking']) && !$r['blocking'] ? 
     182                                                        array('curl', 'streams', 'fsockopen', 'exthttp') : // non-blocking order 
     183                                                        array('exthttp', 'curl', 'streams', 'fsockopen'); // blocking order 
    321184 
    322                         if ( ! is_wp_error( $response ) ) 
    323                                 return apply_filters( 'http_response', $response, $r, $url ); 
    324                 } 
     185                // This loops over each transport on each HTTP request looking for one which will serve it's needs 
     186                foreach ( $request_order as $transport ) { 
     187                        $class = 'WP_HTTP_' . $transport; 
    325188 
    326                 return $response; 
     189                        // Check to see if this transport is a possibility 
     190                        if ( ! $class::test($r, $url) ) //Note: ::test() does not use $url 
     191                                continue; 
     192 
     193                        // Class claims to support request, Instantate it and give it a whirl. 
     194                        if ( empty($transports[$transport]) ) 
     195                                $transports[$transport] = new $class; 
     196 
     197                        // Make the request already! 
     198                        $response = $transports[$transport]->request( $url, $r ); 
     199 
     200                        do_action( 'http_api_debug', $response, 'response', $class ); 
     201 
     202                        // Remove this If block to have pre-3.2 style responses, ie. Only try *one* transport then give up, 
     203                        // Putting this here as a possibility for enabling requests to attmept another transport if it fails 
     204                        //  or as a means to do staged-backoff's in times where requests consistently fail with a transport 
     205                        //  as happens with cURL on some errors on certain hosts. 
     206                        if ( is_wp_error( $response ) ) { 
     207                                // Set an increasing count of transport failures? Ie. If cURL fails 3 times, just discard it? 
     208                                //get_transient(); set_transient(); 
     209 
     210                                // If the arg 'try-other-transports' is set, and this request failed, Try the next transport instead of failure. 
     211                                if ( !empty($r['try-other-transports']) ) 
     212                                        continue; 
     213                        } 
     214 
     215                        return apply_filters( 'http_response', $response, $r, $url ); 
     216                } 
     217                // Pre-3.2 this would've been returned in the event that nothing could handle it: 
     218                // array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); 
     219                return new WP_Error('http_failure', __('HTTP Failure - There are no transports available which can serve your request.')); //@TODO: String change 
    327220        } 
    328221 
    329222        /** 
     
    789682         * @static 
    790683         * @return boolean False means this class can not be used, true means it can. 
    791684         */ 
    792         function test( $args = array() ) { 
     685        function test( $args = array() ) { //fsockopen 
    793686                if ( false !== ($option = get_option( 'disable_fsockopen' )) && time()-$option < 43200 ) // 12 hours 
    794687                        return false; 
    795688 
     
    928821         * @static 
    929822         * @return boolean False means this class can not be used, true means it can. 
    930823         */ 
    931         function test($args = array()) { 
     824        function test($args = array()) { //fopen 
    932825                if ( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) ) 
    933826                        return false; 
    934827 
     
    1104997         * 
    1105998         * @return boolean False means this class can not be used, true means it can. 
    1106999         */ 
    1107         function test($args = array()) { 
     1000        function test($args = array()) { //streams 
    11081001                if ( ! function_exists('fopen') || (function_exists('ini_get') && true != ini_get('allow_url_fopen')) ) 
    11091002                        return false; 
    11101003 
     
    12751168         * 
    12761169         * @return boolean False means this class can not be used, true means it can. 
    12771170         */ 
    1278         function test($args = array()) { 
     1171        function test($args = array()) { //ext 
    12791172                return apply_filters('use_http_extension_transport', function_exists('http_request'), $args ); 
    12801173        } 
    12811174} 
     
    14701363         * 
    14711364         * @return boolean False means this class can not be used, true means it can. 
    14721365         */ 
    1473         function test($args = array()) { 
     1366        function test($args = array()) { //curl 
    14741367                if ( function_exists('curl_init') && function_exists('curl_exec') ) 
    14751368                        return apply_filters('use_curl_transport', true, $args); 
    14761369