diff --git a/php/utils.php b/php/utils.php index 46796053ef..d17df88ff5 100644 --- a/php/utils.php +++ b/php/utils.php @@ -580,13 +580,16 @@ function http_request( $method, $url, $data = null, $headers = array(), $options $request = \Requests::request( $url, $headers, $data, $method, $options ); return $request; } catch( \Requests_Exception $ex ) { + if ( 'curlerror' !== $ex->getType() || ! in_array( curl_errno( $ex->getData() ), array( CURLE_SSL_CONNECT_ERROR, CURLE_SSL_CERTPROBLEM, 77 /*CURLE_SSL_CACERT_BADFILE*/ ), true ) ) { + \WP_CLI::error( sprintf( "Failed to get url '%s': %s.", $url, $ex->getMessage() ) ); + } // Handle SSL certificate issues gracefully - \WP_CLI::warning( $ex->getMessage() ); + \WP_CLI::warning( sprintf( "Re-trying without verify after failing to get verified url '%s' %s.", $url, $ex->getMessage() ) ); $options['verify'] = false; try { return \Requests::request( $url, $headers, $data, $method, $options ); } catch( \Requests_Exception $ex ) { - \WP_CLI::error( $ex->getMessage() ); + \WP_CLI::error( sprintf( "Failed to get non-verified url '%s' %s.", $url, $ex->getMessage() ) ); } } } diff --git a/tests/test-utils.php b/tests/test-utils.php index ec3e795645..fe3d423e52 100644 --- a/tests/test-utils.php +++ b/tests/test-utils.php @@ -2,6 +2,8 @@ use WP_CLI\Utils; +require_once dirname( __DIR__ ) . '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/php/class-wp-cli.php'; + class UtilsTest extends PHPUnit_Framework_TestCase { function testIncrementVersion() { @@ -352,4 +354,93 @@ public function testLaunchEditorForInputProcDisabled() { $this->assertTrue( false !== strpos( trim( $output[0] ), $err_msg ) ); } + public function testHttpRequestBadAddress() { + // Save WP_CLI state. + $class_wp_cli_logger = new \ReflectionProperty( 'WP_CLI', 'logger' ); + $class_wp_cli_logger->setAccessible( true ); + $class_wp_cli_capture_exit = new \ReflectionProperty( 'WP_CLI', 'capture_exit' ); + $class_wp_cli_capture_exit->setAccessible( true ); + + $prev_logger = $class_wp_cli_logger->getValue(); + $prev_capture_exit = $class_wp_cli_capture_exit->getValue(); + + // Enable exit exception. + $class_wp_cli_capture_exit->setValue( true ); + + $logger = new \WP_CLI\Loggers\Execution; + WP_CLI::set_logger( $logger ); + + $exception = null; + try { + Utils\http_request( 'GET', 'https://nosuchhost_asdf_asdf_asdf.com' ); + } catch ( \WP_CLI\ExitException $ex ) { + $exception = $ex; + } + $this->assertTrue( null !== $exception ); + $this->assertTrue( 1 === $exception->getCode() ); + $this->assertTrue( empty( $logger->stdout ) ); + $this->assertTrue( 0 === strpos( $logger->stderr, 'Error: Failed to get url' ) ); + + // Restore. + $class_wp_cli_logger->setValue( $prev_logger ); + $class_wp_cli_capture_exit->setValue( $prev_capture_exit ); + } + + public function testHttpRequestBadCAcert() { + // Save WP_CLI state. + $class_wp_cli_logger = new \ReflectionProperty( 'WP_CLI', 'logger' ); + $class_wp_cli_logger->setAccessible( true ); + + $prev_logger = $class_wp_cli_logger->getValue(); + + $have_bad_cacert = false; + $created_dirs = array(); + + $vendor_dir = WP_CLI_ROOT . '/../../../vendor'; + $cert_path = '/rmccue/requests/library/Requests/Transport/cacert.pem'; + $bad_cacert_path = $vendor_dir . $cert_path; + if ( ! file_exists( $bad_cacert_path ) ) { + // Capture any directories created so can clean up. + $dirs = array_merge( array( 'vendor' ), array_filter( explode( '/', dirname( $cert_path ) ) ) ); + $current_dir = dirname( $vendor_dir ); + foreach ( $dirs as $dir ) { + if ( ! file_exists( $current_dir . '/' . $dir ) ) { + if ( ! @mkdir( $current_dir . '/' . $dir ) ) { + break; + } + $created_dirs[] = $current_dir . '/' . $dir; + } + $current_dir .= '/' . $dir; + } + if ( $current_dir === dirname( $bad_cacert_path ) && file_put_contents( $bad_cacert_path, "-----BEGIN CERTIFICATE-----\nasdfasdf\n-----END CERTIFICATE-----\n" ) ) { + $have_bad_cacert = true; + } + } + + if ( ! $have_bad_cacert ) { + foreach ( array_reverse( $created_dirs ) as $created_dir ) { + rmdir( $created_dir ); + } + $this->markTestSkipped( 'Unable to create bad CAcert.' ); + } + + $logger = new \WP_CLI\Loggers\Execution; + WP_CLI::set_logger( $logger ); + + Utils\http_request( 'GET', 'https://example.com' ); + + // Undo bad CAcert stuff before asserting. + unlink( $bad_cacert_path ); + foreach ( array_reverse( $created_dirs ) as $created_dir ) { + rmdir( $created_dir ); + } + + $this->assertTrue( empty( $logger->stdout ) ); + $this->assertTrue( 0 === strpos( $logger->stderr, 'Warning: Re-trying without verify after failing to get verified url' ) ); + $this->assertFalse( strpos( $logger->stderr, 'Error' ) ); + + // Restore. + $class_wp_cli_logger->setValue( $prev_logger ); + } + }