﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	severity	resolution	keywords	cc
17251	Determine if any WP_HTTP transport can be used before making the request	mdawaffe	dd32	"It can be useful to know if any WP_HTTP transport passes its {{{::test()}}} before making the corresponding request.

For example, consider OAuth.

Some OAuth providers (servers) offer both HTTP and HTTPS APIs (say http://api.example.com/ and https://api.example.com/) and leave it up to the Consumer (client) to decide which to use.  The same request, however, cannot be made to both http://api.example.com/ and https://api.example.com/ because of the way the OAuth signature is calculated: the request URL is part of the hash.  To calculate the signature, you have to know whether you will make an HTTP or an HTTPS request.

Some WordPress installations cannot make outgoing HTTPS requests because their hosts have disabled the OpenSSL extension.  On such hosts, plugins would ideally use the HTTPS API and fallback to the HTTP API.   It is not currently convenient to use WP_HTTP's {{{::test()}}}s to determine ahead of time if outgoing HTTPS requests are possible.

Currently, plugins can do something like the following.

{{{
list( $url_signed, $args_signed ) = oauth_sign_request( $url, $args );
$request = wp_remote_request( $url_signed, $args_signed );
if ( is_wp_error( $request ) && 'http_failure' == $request->get_error_code() ) {
   // HTTPS -> HTTP
   $url = substr_replace( $url, '', 4, 1 );
   list( $url_signed, $args_signed ) = oauth_sign_request( $url, $args );
   $request = wp_remote_request( $url_signed, $args_signed );
}
}}}

The above is inefficient since the OAuth signature must be calculated twice and the {{{::test()}}}s must be run twice.

Attached:
 * Adds new {{{WP_Http::get_first_available_transport( $url, $args )}}} method which returns the first transport to pass its {{{::test( $args, $url )}}}.
 * Adds a new {{{transport_class}}} option to {{{WP_Http::request()}}} so that the {{{::test()}}}s don't have to be run multiple times.

The patch allows the following:

{{{
$http = _wp_http_get_object();
$args['ssl'] = true;
if ( $transport_class = $http->get_first_available_transport( $url, $args ) ) {
   // We already know which one to use
   $args['transport_class'] = $transport_class;
} else {
   // HTTPS -> HTTP
   $url = substr_replace( $url, '', 4, 1 );
   $args['ssl'] = false;
} 
list( $url_signed, $args_signed ) = oauth_sign_request( $url, $args );
$request = wp_remote_request( $url_signed, $args_signed );
}}}

In this snip, both the {{{::test()}}}s and the OAuth signature are only run once.  There's a few extra lines in this snip than in the previous one.  Those lines could be removed with a couple straightforward tweaks to the patch.

See #16606, which also deals with making the WP_HTTP transports and their {{{::test()}}}s more useful."	defect (bug)	closed	normal	3.2	HTTP	3.2	normal	fixed	has-patch	
