WP_HTTP: Abstract out the Redirection handling code into it's own method and fix a bunch of redirection edgecases at the same time.

Fixes #17588
Fixes 16889
Props wonderboymusic and kovshenin for initial patches


git-svn-id: http://core.svn.wordpress.org/trunk@24843 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Dion Hulse 2013-07-29 01:19:54 +00:00
parent d8f819fdda
commit c61a2dac03

View File

@ -593,6 +593,40 @@ class WP_Http {
return $absolute_path . '/' . ltrim( $path, '/' );
}
/**
* Handles HTTP Redirects and follows them if appropriate.
*
* @since 3.7
*
* @param $url The URL which was requested
* @param $args The Arguements which were used to make the request
* @param $response The Response of the HTTP request
* @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise
*/
static function handle_redirects( $url, $args, $response ) {
// If no redirects are present, or, redirects were not requested, perform no action.
if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] )
return false;
// Only perform redirections on redirection http codes
if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 )
return false;
// Don't redirect if we've run out of redirects
if ( $args['redirection']-- <= 0 )
return new WP_Error( 'http_request_failed', __('Too many redirects.') );
$redirect_location = WP_HTTP::make_absolute_url( $response['headers']['location'], $url );
// POST requests should not POST to a redirected location
if ( 'POST' == $args['method'] ) {
if ( in_array( $response['response']['code'], array( 302, 303 ) ) )
$args['method'] = 'GET';
}
return wp_remote_request( $redirect_location, $args );
}
}
/**
@ -804,14 +838,17 @@ class WP_Http_Fsockopen {
$arrHeaders = WP_Http::processHeaders( $process['headers'] );
// If location is found, then assume redirect and redirect to location.
if ( isset($arrHeaders['headers']['location']) && 0 !== $r['_redirection'] ) {
if ( $r['redirection']-- > 0 ) {
return wp_remote_request( WP_HTTP::make_absolute_url( $arrHeaders['headers']['location'], $url ), $r);
} else {
return new WP_Error('http_request_failed', __('Too many redirects.'));
}
}
$response = array(
'headers' => $arrHeaders['headers'],
'body' => null, // Not yet processed
'response' => $arrHeaders['response'],
'cookies' => $arrHeaders['cookies'],
'filename' => $r['filename']
);
// Handle redirects
if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )
return $redirect_response;
// If the body was chunk encoded, then decode it.
if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] )
@ -823,7 +860,9 @@ class WP_Http_Fsockopen {
if ( isset( $r['limit_response_size'] ) && strlen( $process['body'] ) > $r['limit_response_size'] )
$process['body'] = substr( $process['body'], 0, $r['limit_response_size'] );
return array( 'headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename'] );
$response['body'] = $process['body'];
return $response;
}
/**
@ -995,13 +1034,17 @@ class WP_Http_Streams {
else
$processedHeaders = WP_Http::processHeaders($meta['wrapper_data']);
if ( ! empty( $processedHeaders['headers']['location'] ) && 0 !== $r['_redirection'] ) { // _redirection: The requested number of redirections
if ( $r['redirection']-- > 0 ) {
return wp_remote_request( WP_HTTP::make_absolute_url( $processedHeaders['headers']['location'], $url ), $r );
} else {
return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) );
}
}
$response = array(
'headers' => $processedHeaders['headers'],
'body' => null,
'response' => $processedHeaders['response'],
'cookies' => $processedHeaders['cookies'],
'filename' => $r['filename']
);
// Handle redirects
if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )
return $redirect_response;
if ( ! empty( $strResponse ) && isset( $processedHeaders['headers']['transfer-encoding'] ) && 'chunked' == $processedHeaders['headers']['transfer-encoding'] )
$strResponse = WP_Http::chunkTransferDecode($strResponse);
@ -1009,7 +1052,9 @@ class WP_Http_Streams {
if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders['headers']) )
$strResponse = WP_Http_Encoding::decompress( $strResponse );
return array( 'headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies'], 'filename' => $r['filename'] );
$response['body'] = $strResponse;
return $response;
}
/**
@ -1262,19 +1307,24 @@ class WP_Http_Curl {
if ( $r['stream'] )
fclose( $this->stream_handle );
// See #11305 - When running under safe mode, redirection is disabled above. Handle it manually.
if ( ! empty( $theHeaders['headers']['location'] ) && 0 !== $r['_redirection'] ) { // _redirection: The requested number of redirections
if ( $r['redirection']-- > 0 ) {
return wp_remote_request( WP_HTTP::make_absolute_url( $theHeaders['headers']['location'], $url ), $r );
} else {
return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) );
}
}
$response = array(
'headers' => $theHeaders['headers'],
'body' => null,
'response' => $response,
'cookies' => $theHeaders['cookies'],
'filename' => $r['filename']
);
// Handle redirects
if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) )
return $redirect_response;
if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) )
$theBody = WP_Http_Encoding::decompress( $theBody );
return array( 'headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies'], 'filename' => $r['filename'] );
$response['body'] = $theBody;
return $response;
}
/**