Make WordPress Core


Ignore:
Timestamp:
03/04/2013 04:24:26 AM (14 years ago)
Author:
dd32
Message:

WP_HTTP: Enable developers to request the first x bytes of a document using the 'limit-response-size' parameter.
The connection to the remote server will be disconnected after x number of bytes has been received.
See #23472

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/class-http.php

    r23603 r23605  
    9696                        'sslverify' => true,
    9797                        'stream' => false,
    98                         'filename' => null
     98                        'filename' => null,
     99                        'limit-response-size' => null,
    99100                );
    100101
     
    734735                $strResponse = '';
    735736                $bodyStarted = false;
     737                $keep_reading = true;
     738                $block_size = 4096;
     739                if ( isset( $r['limit-response-size'] ) )
     740                        $block_size = min( $block_size, $r['limit-response-size'] );
    736741
    737742                // If streaming to a file setup the file handle
     
    744749                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) );
    745750
    746                         while ( ! feof($handle) ) {
    747                                 $block = fread( $handle, 4096 );
    748                                 if ( $bodyStarted ) {
    749                                         fwrite( $stream_handle, $block );
    750                                 } else {
     751                        $bytes_written = 0;
     752                        while ( ! feof($handle) && $keep_reading ) {
     753                                $block = fread( $handle, $block_size );
     754                                if ( ! $bodyStarted ) {
    751755                                        $strResponse .= $block;
    752756                                        if ( strpos( $strResponse, "\r\n\r\n" ) ) {
    753757                                                $process = WP_Http::processResponse( $strResponse );
    754758                                                $bodyStarted = true;
    755                                                 fwrite( $stream_handle, $process['body'] );
     759                                                $block = $process['body'];
    756760                                                unset( $strResponse );
    757761                                                $process['body'] = '';
    758762                                        }
    759763                                }
     764                               
     765                                if ( isset( $r['limit-response-size'] ) && ( $bytes_written + strlen( $block ) ) > $r['limit-response-size'] )
     766                                        $block = substr( $block, 0, ( $r['limit-response-size'] - $bytes_written ) );
     767
     768                                $bytes_written += fwrite( $stream_handle, $block );                             
     769                               
     770                                $keep_reading = !isset( $r['limit-response-size'] ) || $bytes_written < $r['limit-response-size'];
    760771                        }
    761772
     
    763774
    764775                } else {
    765                         while ( ! feof($handle) )
    766                                 $strResponse .= fread( $handle, 4096 );
     776                        $header_length = 0;
     777                        while ( ! feof( $handle ) && $keep_reading ) {
     778                                $block = fread( $handle, $block_size );
     779                                $strResponse .= $block;
     780                                if ( ! $bodyStarted && strpos( $strResponse, "\r\n\r\n" ) ) {
     781                                        $header_length = strpos( $strResponse, "\r\n\r\n" ) + 4;
     782                                        $bodyStarted = true;
     783                                }
     784                                $keep_reading = ( ! $bodyStarted || !isset( $r['limit-response-size'] ) || strlen( $strResponse ) < ( $header_length + $r['limit-response-size'] ) );
     785                        }
    767786
    768787                        $process = WP_Http::processResponse( $strResponse );
    769788                        unset( $strResponse );
     789
    770790                }
    771791
     
    792812                if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) )
    793813                        $process['body'] = WP_Http_Encoding::decompress( $process['body'] );
     814
     815                if ( isset( $r['limit-response-size'] ) && strlen( $process['body'] ) > $r['limit-response-size'] )
     816                        $process['body'] = substr( $process['body'], 0, $r['limit-response-size'] );
    794817
    795818                return array( 'headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename'] );
     
    937960                }
    938961
     962                $max_bytes = isset( $r['limit-response-size'] ) ? intval( $r['limit-response-size'] ) : -1;
    939963                if ( $r['stream'] ) {
    940964                        if ( ! WP_DEBUG )
     
    946970                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) );
    947971
    948                         stream_copy_to_stream( $handle, $stream_handle );
     972                        stream_copy_to_stream( $handle, $stream_handle, $max_bytes );
    949973
    950974                        fclose( $stream_handle );
    951975                        $strResponse = '';
    952976                } else {
    953                         $strResponse = stream_get_contents( $handle );
     977                        $strResponse = stream_get_contents( $handle, $max_bytes );
    954978                }
    955979
     
    10181042
    10191043        /**
    1020          * Temporary header storage for use with streaming to a file.
     1044         * Temporary header storage for during requests.
    10211045         *
    10221046         * @since 3.2.0
     
    10251049         */
    10261050        private $headers = '';
     1051
     1052        /**
     1053         * Temporary body storage for during requests.
     1054         *
     1055         * @since 3.6.0
     1056         * @access private
     1057         * @var string
     1058         */
     1059        private $body = '';
     1060
     1061        /**
     1062         * The maximum amount of data to recieve from the remote server
     1063         *
     1064         * @since 3.6.0
     1065         * @access private
     1066         * @var int
     1067         */
     1068        private $max_body_length = false;
     1069
     1070        /**
     1071         * The file resource used for streaming to file.
     1072         *
     1073         * @since 3.6.0
     1074         * @access private
     1075         * @var resource
     1076         */
     1077        private $stream_handle = false;
    10271078
    10281079        /**
     
    11151166                }
    11161167
    1117                 if ( true === $r['blocking'] )
     1168                if ( true === $r['blocking'] ) {
    11181169                        curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'stream_headers' ) );
     1170                        curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'stream_body' ) );
     1171                }
    11191172
    11201173                curl_setopt( $handle, CURLOPT_HEADER, false );
     1174
     1175                if ( isset( $r['limit-response-size'] ) )
     1176                        $this->max_body_length = intval( $r['limit-response-size'] );
    11211177
    11221178                // If streaming to a file open a file handle, and setup our curl streaming handler
    11231179                if ( $r['stream'] ) {
    11241180                        if ( ! WP_DEBUG )
    1125                                 $stream_handle = @fopen( $r['filename'], 'w+' );
     1181                                $this->stream_handle = @fopen( $r['filename'], 'w+' );
    11261182                        else
    1127                                 $stream_handle = fopen( $r['filename'], 'w+' );
    1128                         if ( ! $stream_handle )
     1183                                $this->stream_handle = fopen( $r['filename'], 'w+' );
     1184                        if ( ! $this->stream_handle )
    11291185                                return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) );
    1130                         curl_setopt( $handle, CURLOPT_FILE, $stream_handle );
    11311186                }
    11321187
     
    11571212
    11581213                $theResponse = curl_exec( $handle );
    1159                 $theBody = '';
    11601214                $theHeaders = WP_Http::processHeaders( $this->headers );
    1161 
    1162                 if ( strlen($theResponse) > 0 && ! is_bool( $theResponse ) ) // is_bool: when using $args['stream'], curl_exec will return (bool)true
    1163                         $theBody = $theResponse;
     1215                $theBody = $this->body;
     1216
     1217                $this->headers = '';
     1218                $this->body = '';
    11641219
    11651220                // If no response
    1166                 if ( 0 == strlen( $theResponse ) && empty( $theHeaders['headers'] ) ) {
     1221                if ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) {
    11671222                        if ( $curl_error = curl_error( $handle ) )
    11681223                                return new WP_Error( 'http_request_failed', $curl_error );
     
    11711226                }
    11721227
    1173                 $this->headers = '';
    1174 
    11751228                $response = array();
    11761229                $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE );
     
    11801233
    11811234                if ( $r['stream'] )
    1182                         fclose( $stream_handle );
     1235                        fclose( $this->stream_handle );
    11831236
    11841237                // See #11305 - When running under safe mode, redirection is disabled above. Handle it manually.
     
    12091262                $this->headers .= $headers;
    12101263                return strlen( $headers );
     1264        }
     1265
     1266        /**
     1267         * Grab the body of the cURL request
     1268         *
     1269         * The contents of the document are passed in chunks, so we append to the $body property for temporary storage.
     1270         * Returning a length shorter than the length of $data passed in will cause cURL to abort the request as "completed"
     1271         *
     1272         * @since 3.6.0
     1273         * @access private
     1274         * @return int
     1275         */
     1276        private function stream_body( $handle, $data ) {
     1277                if ( $this->max_body_length && ( strlen( $this->body ) + strlen( $data ) ) > $this->max_body_length )
     1278                        $data = substr( $data, 0, ( $this->max_body_length - strlen( $this->body ) ) );
     1279
     1280                if ( $this->stream_handle )
     1281                        fwrite( $this->stream_handle, $data );
     1282                else
     1283                        $this->body .= $data;
     1284
     1285                return strlen( $data );
    12111286        }
    12121287
     
    17451820                elseif ( $args['stream'] ) // disable when streaming to file
    17461821                        $compression_enabled = false;
     1822                elseif ( isset( $args['limit-response-size'] ) ) // If only partial content is being requested, we won't be able to decompress it
     1823                        $compression_enabled = false;
    17471824
    17481825                if ( $compression_enabled ) {
Note: See TracChangeset for help on using the changeset viewer.