Skip to content
2 changes: 1 addition & 1 deletion src/wp-includes/class-wp-http-streams.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class WP_Http_Streams {
/**
* Send a HTTP request to a URI using PHP Streams.
*
* @see WP_Http::request() For default options descriptions.
* @see WP_Http::format_request() For default options descriptions.
*
* @since 2.7.0
* @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client().
Expand Down
205 changes: 181 additions & 24 deletions src/wp-includes/class-wp-http.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class WP_Http {
*
* @since 2.7.0
*
* @param string $url The request URL.
* @param string|array $url The request URL or an array of requests.
* @param string|array $args {
* Optional. Array or string of HTTP request arguments.
*
Expand Down Expand Up @@ -167,6 +167,105 @@ class WP_Http {
* }
*/
public function request( $url, $args = array() ) {
if ( is_array( $url ) ) {
$pending_requests = array();
$responses = array();

foreach ( $url as $index => $request ) {
// Support an array of string URLs.
if ( ! is_array( $request ) ) {
$request = array( $request, array() );
}

$request = $this->format_request( $request[0], isset( $request[1] ) ? $request[1] : array() );

// Handle an error in the pre-request step. Also allow the request to be
// circumvented if the response was short-circuited.
if ( is_wp_error( $request ) ) {
$responses[ $index ] = $request;
continue;
} elseif ( isset( $request['response'] ) ) {
$responses[ $index ] = $request['response'];
continue;
}

$pending_requests[ $index ] = $request;
}

if ( ! empty( $pending_requests ) ) {
// Avoid issues where mbstring.func_overload is enabled.
mbstring_binary_safe_encoding();

try {
$raw_responses = WpOrg\Requests\Requests::request_multiple( $pending_requests );
} catch ( WpOrg\Requests\Exception $e ) {
$raw_responses = new WP_Error( 'http_request_failed', $e->getMessage() );
}

reset_mbstring_encoding();

if ( is_wp_error( $raw_responses ) ) {
return $raw_responses;
}

foreach ( $pending_requests as $index => $request ) {
$responses[ $index ] = $this->format_response(
$raw_responses[ $index ],
$request['args'],
$request['url']
);
}
}

return $responses;
}

$formatted = $this->format_request( $url, $args );

// Handle an error in the pre-request step. Also allow the request to be
// circumvented if the response was short-circuited.
if ( is_wp_error( $formatted ) ) {
return $formatted;
} elseif ( isset( $formatted['response'] ) ) {
return $formatted['response'];
}

// Avoid issues where mbstring.func_overload is enabled.
mbstring_binary_safe_encoding();

try {
$response = WpOrg\Requests\Requests::request(
$formatted['url'],
$formatted['headers'],
$formatted['data'],
$formatted['type'],
$formatted['options']
);
} catch ( WpOrg\Requests\Exception $e ) {
$response = new WP_Error( 'http_request_failed', $e->getMessage() );
}

reset_mbstring_encoding();

return $this->format_response( $response, $formatted['args'], $formatted['url'] );
}

/**
* Format a request to be passed to Requests.
*
* @param string $url URL to request.
* @param array $args Arguments to send to request.
* @return array {
* Array of formatted arguments for the request.
*
* @type string $url URL to request.
* @type array $headers Array of headers for the request.
* @type string $data Data to send with the request.
* @type string $type The type of request to make.
* @type array $options Array of options for the request.
* }
*/
protected function format_request( $url, $args ) {
$defaults = array(
'method' => 'GET',
/**
Expand Down Expand Up @@ -241,6 +340,7 @@ public function request( $url, $args = array() ) {
}

$parsed_args = wp_parse_args( $args, $defaults );

/**
* Filters the arguments used in an HTTP request.
*
Expand Down Expand Up @@ -277,7 +377,9 @@ public function request( $url, $args = array() ) {
$pre = apply_filters( 'pre_http_request', false, $parsed_args, $url );

if ( false !== $pre ) {
return $pre;
return array(
'response' => $pre,
);
}

if ( function_exists( 'wp_kses_bad_protocol' ) ) {
Expand Down Expand Up @@ -408,24 +510,38 @@ public function request( $url, $args = array() ) {
}
}

// Avoid issues where mbstring.func_overload is enabled.
mbstring_binary_safe_encoding();
return array(
'args' => $parsed_args,
'data' => $data,
'headers' => $headers,
'options' => $options,
'type' => $type,
'url' => $url,
);
}

try {
$requests_response = WpOrg\Requests\Requests::request( $url, $headers, $data, $type, $options );
/**
* Format a response into the expected shape.
*
* @param \WpOrg\Requests\Response|\WpOrg\Requests\Exception|WP_Error $response Response to format.
* @param array $args Request arguments.
* @param string $url Request URL.
* @return array|WP_Error
*/
protected function format_response( $response, $args, $url ) {
if ( $response instanceof \WpOrg\Requests\Exception ) {
$response = new \WP_Error( 'http_request_failed', $response->getMessage() );
}

// Convert the response into an array.
$http_response = new WP_HTTP_Requests_Response( $requests_response, $parsed_args['filename'] );
// Convert the response into an array.
if ( ! is_wp_error( $response ) ) {
$http_response = new WP_HTTP_Requests_Response( $response, $args['filename'] );
$response = $http_response->to_array();

// Add the original object to the array.
$response['http_response'] = $http_response;
} catch ( WpOrg\Requests\Exception $e ) {
$response = new WP_Error( 'http_request_failed', $e->getMessage() );
}

reset_mbstring_encoding();

/**
* Fires after an HTTP API response is received and before the response is returned.
*
Expand All @@ -434,15 +550,16 @@ public function request( $url, $args = array() ) {
* @param array|WP_Error $response HTTP response or WP_Error object.
* @param string $context Context under which the hook is fired.
* @param string $class HTTP transport used.
* @param array $parsed_args HTTP request arguments.
* @param array $args HTTP request arguments.
* @param string $url The request URL.
*/
do_action( 'http_api_debug', $response, 'response', 'WpOrg\Requests\Requests', $parsed_args, $url );
do_action( 'http_api_debug', $response, 'response', \WpOrg\Requests\Requests::class, $args, $url );

if ( is_wp_error( $response ) ) {
return $response;
}

if ( ! $parsed_args['blocking'] ) {
if ( ! $args['blocking'] ) {
return array(
'headers' => array(),
'body' => '',
Expand All @@ -464,7 +581,7 @@ public function request( $url, $args = array() ) {
* @param array $parsed_args HTTP request arguments.
* @param string $url The request URL.
*/
return apply_filters( 'http_response', $response, $parsed_args, $url );
return apply_filters( 'http_response', $response, $args, $url );
}

/**
Expand Down Expand Up @@ -633,9 +750,7 @@ private function _dispatch_request( $url, $args ) {
* A WP_Error instance upon error. See WP_Http::response() for details.
*/
public function post( $url, $args = array() ) {
$defaults = array( 'method' => 'POST' );
$parsed_args = wp_parse_args( $args, $defaults );
return $this->request( $url, $parsed_args );
return $this->normalize_request_args( $url, $args, 'POST' );
}

/**
Expand All @@ -645,15 +760,13 @@ public function post( $url, $args = array() ) {
*
* @since 2.7.0
*
* @param string $url The request URL.
* @param string|array $url The request URL or array of remote requests that will be run in parallel.
* @param string|array $args Optional. Override the defaults.
* @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'.
* A WP_Error instance upon error. See WP_Http::response() for details.
*/
public function get( $url, $args = array() ) {
$defaults = array( 'method' => 'GET' );
$parsed_args = wp_parse_args( $args, $defaults );
return $this->request( $url, $parsed_args );
return $this->normalize_request_args( $url, $args, 'GET' );
}

/**
Expand All @@ -669,8 +782,52 @@ public function get( $url, $args = array() ) {
* A WP_Error instance upon error. See WP_Http::response() for details.
*/
public function head( $url, $args = array() ) {
$defaults = array( 'method' => 'HEAD' );
return $this->normalize_request_args( $url, $args, 'HEAD' );
}

/**
* Normalize the request arguments for a GET, HEAD, or POST request.
*
* @param string|array $url The request URL or array of remote requests that will be run in parallel.
* @param string|array $args Request arguments, optional. Override the defaults.
* @param string $method Request method to make.
* @return array Array containing 'headers', 'body', 'response', 'cookies', 'filename'.
* A WP_Error instance upon error.
*/
protected function normalize_request_args( $url, $args, $method ) {
$defaults = array( 'method' => $method );

// Support an array of parallel requests.
if ( is_array( $url ) ) {
$parsed_requests = array();

if ( ! empty( $args ) ) {
_doing_it_wrong(
__FUNCTION__,
__( 'Arguments passed to the second $args parameter are ignored when $url is an array of parallel requests.' ),
'6.0.0'
);
}

foreach ( $url as $i => $request ) {
// Support an array of string URLs.
if ( ! is_array( $request ) ) {
$request = array( $request, array() );
}

list( $request_url, $request_args ) = $request;

$parsed_requests[ $i ] = array(
$request_url,
wp_parse_args( $request_args, $defaults ),
);
}

return $this->request( $parsed_requests );
}

$parsed_args = wp_parse_args( $args, $defaults );

return $this->request( $url, $parsed_args );
}

Expand Down
30 changes: 15 additions & 15 deletions src/wp-includes/http.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ function wp_safe_remote_head( $url, $args = array() ) {
*
* @since 2.7.0
*
* @see WP_Http::request() For information on default arguments.
* @see WP_Http::format_request() For information on default arguments.
*
* @param string $url URL to retrieve.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @param string|array $url URL to retrieve or array of remote requests that will be run in parallel.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @return array|WP_Error The response array or a WP_Error on failure.
* See WP_Http::request() for information on return value.
*/
Expand All @@ -178,9 +178,9 @@ function wp_remote_request( $url, $args = array() ) {
* @see wp_remote_request() For more information on the response array format.
* @see WP_Http::request() For default arguments information.
*
* @param string $url URL to retrieve.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @param string|array $url URL to retrieve or array of remote requests that will be run in parallel.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @return array|WP_Error The response or WP_Error on failure.
* See WP_Http::request() for information on return value.
*/
Expand All @@ -197,11 +197,11 @@ function wp_remote_get( $url, $args = array() ) {
* @since 2.7.0
*
* @see wp_remote_request() For more information on the response array format.
* @see WP_Http::request() For default arguments information.
* @see WP_Http::format_request() For default arguments information.
*
* @param string $url URL to retrieve.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @param string|array $url URL to retrieve or array of remote requests that will be run in parallel.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @return array|WP_Error The response or WP_Error on failure.
* See WP_Http::request() for information on return value.
*/
Expand All @@ -218,11 +218,11 @@ function wp_remote_post( $url, $args = array() ) {
* @since 2.7.0
*
* @see wp_remote_request() For more information on the response array format.
* @see WP_Http::request() For default arguments information.
* @see WP_Http::format_request() For default arguments information.
*
* @param string $url URL to retrieve.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @param string|array $url URL to retrieve or array of remote requests that will be run in parallel.
* @param array $args Optional. Request arguments. Default empty array.
* See WP_Http::request() for information on accepted arguments.
* @return array|WP_Error The response or WP_Error on failure.
* See WP_Http::request() for information on return value.
*/
Expand Down
Loading
Loading