diff --git a/README.md b/README.md index 20a67fb..e3a9a09 100644 --- a/README.md +++ b/README.md @@ -67,8 +67,11 @@ Once [installed](#install), you can use the following code to query an example web service via SOAP: ```php -$loop = React\EventLoop\Factory::create(); -$browser = new React\Http\Browser($loop); +get($wsdl)->then(function (Psr\Http\Message\ResponseInterface $response) use ($browser) { @@ -79,8 +82,6 @@ $browser->get($wsdl)->then(function (Psr\Http\Message\ResponseInterface $respons var_dump('Result', $result); }); }); - -$loop->run(); ``` See also the [examples](examples). @@ -90,30 +91,26 @@ See also the [examples](examples). ### Client The `Client` class is responsible for communication with the remote SOAP -WebService server. - -It requires a [`Browser`](https://github.com/reactphp/http#browser) object -bound to the main [`EventLoop`](https://github.com/reactphp/event-loop#usage) -in order to handle async requests, the WSDL file contents and an optional +WebService server. It requires the WSDL file contents and an optional array of SOAP options: ```php -$loop = React\EventLoop\Factory::create(); -$browser = new React\Http\Browser($loop); - $wsdl = ' '127.0.0.1', 'tcp' => array( 'bindto' => '192.168.10.1:0' @@ -124,7 +121,7 @@ $connector = new React\Socket\Connector($loop, array( ) )); -$browser = new React\Http\Browser($loop, $connector); +$browser = new React\Http\Browser($connector); $client = new Clue\React\Soap\Client($browser, $wsdl); ``` @@ -134,7 +131,7 @@ you to use local WSDL files, WSDL files from a cache or the most common form, downloading the WSDL file contents from an URL through the `Browser`: ```php -$browser = new React\Http\Browser($loop); +$browser = new React\Http\Browser(); $browser->get($url)->then( function (Psr\Http\Message\ResponseInterface $response) use ($browser) { @@ -155,7 +152,7 @@ parsed, this will throw a `SoapFault`: ```php try { - $client = new Clue\React\Soap\Client($browser, $wsdl); + $client = new Clue\React\Soap\Client(null, $wsdl); } catch (SoapFault $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; } @@ -179,7 +176,7 @@ the URL of the SOAP server to send the request to, and `uri` is the target namespace of the SOAP service: ```php -$client = new Clue\React\Soap\Client($browser, null, array( +$client = new Clue\React\Soap\Client(null, null, array( 'location' => 'http://example.com', 'uri' => 'http://ping.example.com', )); @@ -189,7 +186,7 @@ Similarly, if working in WSDL mode, the `location` option can be used to explicitly overwrite the URL of the SOAP server to send the request to: ```php -$client = new Clue\React\Soap\Client($browser, $wsdl, array( +$client = new Clue\React\Soap\Client(null, $wsdl, array( 'location' => 'http://example.com' )); ``` @@ -198,7 +195,7 @@ You can use the `soap_version` option to change from the default SOAP 1.1 to use SOAP 1.2 instead: ```php -$client = new Clue\React\Soap\Client($browser, $wsdl, array( +$client = new Clue\React\Soap\Client(null, $wsdl, array( 'soap_version' => SOAP_1_2 )); ``` @@ -207,7 +204,7 @@ You can use the `classmap` option to map certain WSDL types to PHP classes like this: ```php -$client = new Clue\React\Soap\Client($browser, $wsdl, array( +$client = new Clue\React\Soap\Client(null, $wsdl, array( 'classmap' => array( 'getBankResponseType' => BankResponse::class ) @@ -366,7 +363,7 @@ clean up any underlying resources. ```php $promise = $proxy->demo(); -$loop->addTimer(2.0, function () use ($promise) { +Loop::addTimer(2.0, function () use ($promise) { $promise->cancel(); }); ``` @@ -389,7 +386,7 @@ pass the timeout to the [underlying `Browser`](https://github.com/reactphp/http# like this: ```php -$browser = new React\Http\Browser($loop); +$browser = new React\Http\Browser(); $browser = $browser->withTimeout(10.0); $client = new Clue\React\Soap\Client($browser, $wsdl); diff --git a/composer.json b/composer.json index c2a918e..d5b7a47 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ }, "require": { "php": ">=7.1", - "react/http": "^1.0", + "react/http": "^1.5", "react/promise": "^2.1 || ^1.2", "ext-soap": "*" }, diff --git a/examples/01-client-blz-wsdl.php b/examples/01-client-blz-wsdl.php index 2265cdd..c1b91a2 100644 --- a/examples/01-client-blz-wsdl.php +++ b/examples/01-client-blz-wsdl.php @@ -2,8 +2,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$browser = new React\Http\Browser($loop); +$browser = new React\Http\Browser(); $blz = isset($argv[1]) ? $argv[1] : '12070000'; @@ -21,5 +20,3 @@ function (Exception $e) { } ); }); - -$loop->run(); diff --git a/examples/02-client-blz-non-wsdl.php b/examples/02-client-blz-non-wsdl.php index e2d1d7d..810667c 100644 --- a/examples/02-client-blz-non-wsdl.php +++ b/examples/02-client-blz-non-wsdl.php @@ -2,12 +2,9 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$browser = new React\Http\Browser($loop); - $blz = isset($argv[1]) ? $argv[1] : '12070000'; -$client = new Clue\React\Soap\Client($browser, null, array( +$client = new Clue\React\Soap\Client(null, null, array( 'location' => 'http://www.thomas-bayer.com/axis2/services/BLZService', 'uri' => 'http://thomas-bayer.com/blz/', 'use' => SOAP_LITERAL @@ -23,5 +20,3 @@ function (Exception $e) { echo 'ERROR: ' . $e->getMessage() . PHP_EOL; } ); - -$loop->run(); diff --git a/examples/11-wsdl-info.php b/examples/11-wsdl-info.php index e471e68..16d306f 100644 --- a/examples/11-wsdl-info.php +++ b/examples/11-wsdl-info.php @@ -2,8 +2,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$loop = React\EventLoop\Factory::create(); -$browser = new React\Http\Browser($loop); +$browser = new React\Http\Browser(); $wsdl = isset($argv[1]) ? $argv[1] : 'http://www.thomas-bayer.com/axis2/services/BLZService?wsdl'; @@ -21,5 +20,3 @@ function (Exception $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; } ); - -$loop->run(); diff --git a/src/Client.php b/src/Client.php index dda7b98..9d820a2 100644 --- a/src/Client.php +++ b/src/Client.php @@ -11,30 +11,26 @@ /** * The `Client` class is responsible for communication with the remote SOAP - * WebService server. - * - * It requires a [`Browser`](https://github.com/reactphp/http#browser) object - * bound to the main [`EventLoop`](https://github.com/reactphp/event-loop#usage) - * in order to handle async requests, the WSDL file contents and an optional + * WebService server. It requires the WSDL file contents and an optional * array of SOAP options: * * ```php - * $loop = React\EventLoop\Factory::create(); - * $browser = new React\Http\Browser($loop); - * * $wsdl = ' '127.0.0.1', * 'tcp' => array( * 'bindto' => '192.168.10.1:0' @@ -45,7 +41,7 @@ * ) * )); * - * $browser = new React\Http\Browser($loop, $connector); + * $browser = new React\Http\Browser($connector); * $client = new Clue\React\Soap\Client($browser, $wsdl); * ``` * @@ -55,7 +51,7 @@ * downloading the WSDL file contents from an URL through the `Browser`: * * ```php - * $browser = new React\Http\Browser($loop); + * $browser = new React\Http\Browser(); * * $browser->get($url)->then( * function (Psr\Http\Message\ResponseInterface $response) use ($browser) { @@ -76,7 +72,7 @@ * * ```php * try { - * $client = new Clue\React\Soap\Client($browser, $wsdl); + * $client = new Clue\React\Soap\Client(null, $wsdl); * } catch (SoapFault $e) { * echo 'Error: ' . $e->getMessage() . PHP_EOL; * } @@ -100,7 +96,7 @@ * namespace of the SOAP service: * * ```php - * $client = new Clue\React\Soap\Client($browser, null, array( + * $client = new Clue\React\Soap\Client(null, null, array( * 'location' => 'http://example.com', * 'uri' => 'http://ping.example.com', * )); @@ -110,7 +106,7 @@ * explicitly overwrite the URL of the SOAP server to send the request to: * * ```php - * $client = new Clue\React\Soap\Client($browser, $wsdl, array( + * $client = new Clue\React\Soap\Client(null, $wsdl, array( * 'location' => 'http://example.com' * )); * ``` @@ -119,7 +115,7 @@ * use SOAP 1.2 instead: * * ```php - * $client = new Clue\React\Soap\Client($browser, $wsdl, array( + * $client = new Clue\React\Soap\Client(null, $wsdl, array( * 'soap_version' => SOAP_1_2 * )); * ``` @@ -128,7 +124,7 @@ * like this: * * ```php - * $client = new Clue\React\Soap\Client($browser, $wsdl, array( + * $client = new Clue\React\Soap\Client(null, $wsdl, array( * 'classmap' => array( * 'getBankResponseType' => BankResponse::class * ) @@ -146,29 +142,32 @@ */ class Client { + /** @var Browser */ private $browser; + private $encoder; private $decoder; /** * Instantiate a new SOAP client for the given WSDL contents. * - * @param Browser $browser - * @param string|null $wsdlContents - * @param array $options + * @param ?Browser $browser + * @param ?string $wsdlContents + * @param ?array $options */ - public function __construct(Browser $browser, ?string $wsdlContents, array $options = array()) + public function __construct(?Browser $browser, ?string $wsdlContents, array $options = array()) { $wsdl = $wsdlContents !== null ? 'data://text/plain;base64,' . base64_encode($wsdlContents) : null; + $this->browser = $browser ?? new Browser(); + // Accept HTTP responses with error status codes as valid responses. // This is done in order to process these error responses through the normal SOAP decoder. // Additionally, we explicitly limit number of redirects to zero because following redirects makes little sense // because it transforms the POST request to a GET one and hence loses the SOAP request body. - $browser = $browser->withRejectErrorResponse(false); - $browser = $browser->withFollowRedirects(0); + $this->browser = $this->browser->withRejectErrorResponse(false); + $this->browser = $this->browser->withFollowRedirects(0); - $this->browser = $browser; $this->encoder = new ClientEncoder($wsdl, $options); $this->decoder = new ClientDecoder($wsdl, $options); } diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 0be4cbc..f18af1d 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -6,6 +6,7 @@ use Clue\React\Soap\Client; use Clue\React\Soap\Proxy; use PHPUnit\Framework\TestCase; +use React\EventLoop\Loop; use React\Http\Browser; class BankResponse @@ -42,8 +43,7 @@ public static function setUpFileBeforeClass() */ public function setUpClient() { - $this->loop = \React\EventLoop\Factory::create(); - $this->client = new Client(new Browser($this->loop), self::$wsdl); + $this->client = new Client(null, self::$wsdl); } public function testBlzService() @@ -55,7 +55,7 @@ public function testBlzService() $promise = $api->getBank(array('blz' => '12070000')); - $result = Block\await($promise, $this->loop); + $result = Block\await($promise, Loop::get()); $this->assertIsObject($result); $this->assertTrue(isset($result->details)); @@ -64,7 +64,7 @@ public function testBlzService() public function testBlzServiceWithClassmapReturnsExpectedType() { - $this->client = new Client(new Browser($this->loop), self::$wsdl, array( + $this->client = new Client(null, self::$wsdl, array( 'classmap' => array( 'getBankResponseType' => 'Clue\Tests\React\Soap\BankResponse' ) @@ -77,7 +77,7 @@ public function testBlzServiceWithClassmapReturnsExpectedType() $promise = $api->getBank(array('blz' => '12070000')); - $result = Block\await($promise, $this->loop); + $result = Block\await($promise, Loop::get()); $this->assertInstanceOf('Clue\Tests\React\Soap\BankResponse', $result); $this->assertTrue(isset($result->details)); @@ -86,7 +86,7 @@ public function testBlzServiceWithClassmapReturnsExpectedType() public function testBlzServiceWithSoapV12() { - $this->client = new Client(new Browser($this->loop), self::$wsdl, array( + $this->client = new Client(null, self::$wsdl, array( 'soap_version' => SOAP_1_2 )); @@ -97,7 +97,7 @@ public function testBlzServiceWithSoapV12() $promise = $api->getBank(array('blz' => '12070000')); - $result = Block\await($promise, $this->loop); + $result = Block\await($promise, Loop::get()); $this->assertIsObject($result); $this->assertTrue(isset($result->details)); @@ -106,7 +106,7 @@ public function testBlzServiceWithSoapV12() public function testBlzServiceNonWsdlModeReturnedWithoutOuterResultStructure() { - $this->client = new Client(new Browser($this->loop), null, array( + $this->client = new Client(null, null, array( 'location' => 'http://www.thomas-bayer.com/axis2/services/BLZService', 'uri' => 'http://thomas-bayer.com/blz/', )); @@ -117,7 +117,7 @@ public function testBlzServiceNonWsdlModeReturnedWithoutOuterResultStructure() // $promise = $api->getBank(new SoapParam('12070000', 'ns1:blz')); $promise = $api->getBank(new \SoapVar('12070000', XSD_STRING, null, null, 'blz', 'http://thomas-bayer.com/blz/')); - $result = Block\await($promise, $this->loop); + $result = Block\await($promise, Loop::get()); $this->assertIsObject($result); $this->assertFalse(isset($result->details)); @@ -126,7 +126,7 @@ public function testBlzServiceNonWsdlModeReturnedWithoutOuterResultStructure() public function testBlzServiceWithRedirectLocationRejectsWithRuntimeException() { - $this->client = new Client(new Browser($this->loop), null, array( + $this->client = new Client(null, null, array( 'location' => 'http://httpbingo.org/redirect-to?url=' . rawurlencode('http://www.thomas-bayer.com/axis2/services/BLZService'), 'uri' => 'http://thomas-bayer.com/blz/', )); @@ -136,7 +136,7 @@ public function testBlzServiceWithRedirectLocationRejectsWithRuntimeException() $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('redirects'); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testBlzServiceWithInvalidBlzRejectsWithSoapFault() @@ -147,7 +147,7 @@ public function testBlzServiceWithInvalidBlzRejectsWithSoapFault() $this->expectException(\SoapFault::class); $this->expectExceptionMessage('Keine Bank zur BLZ invalid gefunden!'); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testBlzServiceWithInvalidMethodRejectsWithSoapFault() @@ -158,7 +158,7 @@ public function testBlzServiceWithInvalidMethodRejectsWithSoapFault() $this->expectException(\SoapFault::class); $this->expectExceptionMessage('Function ("doesNotExist") is not a valid method for this service'); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testCancelMethodRejectsWithRuntimeException() @@ -170,12 +170,12 @@ public function testCancelMethodRejectsWithRuntimeException() $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('cancelled'); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testTimeoutRejectsWithRuntimeException() { - $browser = new Browser($this->loop); + $browser = new Browser(); $browser = $browser->withTimeout(0); $this->client = new Client($browser, self::$wsdl); @@ -185,7 +185,7 @@ public function testTimeoutRejectsWithRuntimeException() $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('timed out'); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testGetLocationForFunctionName() @@ -213,7 +213,7 @@ public function testGetLocationForUnknownFunctionNumberFails() public function testGetLocationWithExplicitLocationOptionReturnsAsIs() { - $this->client = new Client(new Browser($this->loop), self::$wsdl, array( + $this->client = new Client(null, self::$wsdl, array( 'location' => 'http://example.com/' )); @@ -236,7 +236,7 @@ public function testWithLocationInvalidRejectsWithRuntimeException() $promise = $api->getBank(array('blz' => '12070000')); $this->expectException(\RuntimeException::class); - Block\await($promise, $this->loop); + Block\await($promise, Loop::get()); } public function testWithLocationRestoredToOriginalResolves() @@ -248,7 +248,7 @@ public function testWithLocationRestoredToOriginalResolves() $promise = $api->getBank(array('blz' => '12070000')); - $result = Block\await($promise, $this->loop); + $result = Block\await($promise, Loop::get()); $this->assertIsObject($result); } }