From 21d705bbfa76cbfd764a2be3ae97788457aab42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Bechyn=C4=9B?= Date: Fri, 3 Mar 2017 10:56:04 +0100 Subject: [PATCH] SoapClient custom endpoint location & connection keep alive configuration added & tests updated --- src/BeSimple/SoapClient/Curl/CurlOptions.php | 2 +- src/BeSimple/SoapClient/SoapClient.php | 6 ++- .../SoapClient/SoapClientOptionsBuilder.php | 26 ++++++++++ .../SoapOptions/SoapClientOptions.php | 35 +++++++++++-- .../Tests/SoapClientBuilderTest.php | 51 ++++++++++++++++++- .../SoapCommon/SoapOptionsBuilder.php | 40 +++++++++++++++ 6 files changed, 151 insertions(+), 9 deletions(-) diff --git a/src/BeSimple/SoapClient/Curl/CurlOptions.php b/src/BeSimple/SoapClient/Curl/CurlOptions.php index 60ef439..78ca445 100644 --- a/src/BeSimple/SoapClient/Curl/CurlOptions.php +++ b/src/BeSimple/SoapClient/Curl/CurlOptions.php @@ -10,7 +10,7 @@ use BeSimple\SoapClient\SoapServerProxy\SoapServerProxy; class CurlOptions { - const DEFAULT_USER_AGENT = 'BeSimpleSoap'; + const DEFAULT_USER_AGENT = 'PhpBeSimpleSoap'; const SOAP_COMPRESSION_NONE = null; const SOAP_COMPRESSION_GZIP = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP; const SOAP_COMPRESSION_DEFLATE = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE; diff --git a/src/BeSimple/SoapClient/SoapClient.php b/src/BeSimple/SoapClient/SoapClient.php index 6be3a3f..25215b4 100644 --- a/src/BeSimple/SoapClient/SoapClient.php +++ b/src/BeSimple/SoapClient/SoapClient.php @@ -244,12 +244,14 @@ class SoapClient extends \SoapClient { if ($soapRequest->getVersion() === SOAP_1_1) { $headers = [ - 'Content-Type:' . $soapRequest->getContentType(), + 'Content-Type: ' . $soapRequest->getContentType(), 'SOAPAction: "' . $soapRequest->getAction() . '"', + 'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'), ]; } else { $headers = [ - 'Content-Type:' . $soapRequest->getContentType() . '; action="' . $soapRequest->getAction() . '"', + 'Content-Type: ' . $soapRequest->getContentType() . '; action="' . $soapRequest->getAction() . '"', + 'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'), ]; } $curlResponse = $this->curl->executeCurlWithCachedSession( diff --git a/src/BeSimple/SoapClient/SoapClientOptionsBuilder.php b/src/BeSimple/SoapClient/SoapClientOptionsBuilder.php index aa21b45..444817c 100644 --- a/src/BeSimple/SoapClient/SoapClientOptionsBuilder.php +++ b/src/BeSimple/SoapClient/SoapClientOptionsBuilder.php @@ -45,6 +45,19 @@ class SoapClientOptionsBuilder ); } + public static function createWithEndpointLocation($endpointLocation) + { + return new SoapClientOptions( + SoapClientOptions::SOAP_CLIENT_TRACE_ON, + SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, + CurlOptions::DEFAULT_USER_AGENT, + SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, + SoapClientOptions::SOAP_CLIENT_AUTHENTICATION_NONE, + SoapClientOptions::SOAP_CLIENT_PROXY_NONE, + $endpointLocation + ); + } + public static function createWithAuthentication(SoapServerAuthenticationInterface $authentication) { return new SoapClientOptions( @@ -55,4 +68,17 @@ class SoapClientOptionsBuilder $authentication ); } + + public static function createWithAuthenticationAndEndpointLocation($endpointLocation, SoapServerAuthenticationInterface $authentication) + { + return new SoapClientOptions( + SoapClientOptions::SOAP_CLIENT_TRACE_ON, + SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, + CurlOptions::DEFAULT_USER_AGENT, + SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, + $authentication, + SoapClientOptions::SOAP_CLIENT_PROXY_NONE, + $endpointLocation + ); + } } diff --git a/src/BeSimple/SoapClient/SoapOptions/SoapClientOptions.php b/src/BeSimple/SoapClient/SoapOptions/SoapClientOptions.php index fc1e5db..aab8cc9 100644 --- a/src/BeSimple/SoapClient/SoapOptions/SoapClientOptions.php +++ b/src/BeSimple/SoapClient/SoapOptions/SoapClientOptions.php @@ -17,6 +17,8 @@ class SoapClientOptions const SOAP_CLIENT_COMPRESSION_NONE = CurlOptions::SOAP_COMPRESSION_NONE; const SOAP_CLIENT_COMPRESSION_GZIP = CurlOptions::SOAP_COMPRESSION_GZIP; const SOAP_CLIENT_COMPRESSION_DEFLATE = CurlOptions::SOAP_COMPRESSION_DEFLATE; + const SOAP_CLIENT_AUTHENTICATION_NONE = null; + const SOAP_CLIENT_PROXY_NONE = null; private $trace; private $exceptions; @@ -24,23 +26,33 @@ class SoapClientOptions private $compression; private $authentication; private $proxy; + private $location; /** * @param bool $trace = SoapClientOptions::SOAP_CLIENT_TRACE_ON|SoapClientOptions::SOAP_CLIENT_TRACE_OFF * @param bool $exceptions = SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON|SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_OFF * @param string $userAgent - * @param int $compression = SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE|SoapClientOptions::SOAP_CLIENT_COMPRESSION_GZIP|SoapClientOptions::SOAP_CLIENT_COMPRESSION_DEFLATE - * @param SoapServerAuthenticationInterface $authentication = null - * @param SoapServerProxy $proxy = null + * @param int|null $compression = SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE|SoapClientOptions::SOAP_CLIENT_COMPRESSION_GZIP|SoapClientOptions::SOAP_CLIENT_COMPRESSION_DEFLATE + * @param SoapServerAuthenticationInterface|null $authentication + * @param SoapServerProxy|null $proxy + * @param string|null $location */ - public function __construct($trace, $exceptions, $userAgent, $compression = null, SoapServerAuthenticationInterface $authentication = null, SoapServerProxy $proxy = null) - { + public function __construct( + $trace, + $exceptions, + $userAgent, + $compression = null, + SoapServerAuthenticationInterface $authentication = null, + SoapServerProxy $proxy = null, + $location = null + ) { $this->trace = $trace; $this->exceptions = $exceptions; $this->userAgent = $userAgent; $this->compression = $compression; $this->authentication = $authentication; $this->proxy = $proxy; + $this->location = $location; } public function getTrace() @@ -88,6 +100,11 @@ class SoapClientOptions return $this->proxy !== null; } + public function hasLocation() + { + return $this->location !== null; + } + public function getAuthentication() { return $this->authentication; @@ -98,6 +115,11 @@ class SoapClientOptions return $this->proxy; } + public function getLocation() + { + return $this->location; + } + public function toArray() { $optionsAsArray = [ @@ -114,6 +136,9 @@ class SoapClientOptions if ($this->hasProxy()) { $optionsAsArray += $this->getProxy()->toArray(); } + if ($this->hasLocation()) { + $optionsAsArray['location'] = $this->getLocation(); + } return $optionsAsArray; } diff --git a/src/BeSimple/SoapClient/Tests/SoapClientBuilderTest.php b/src/BeSimple/SoapClient/Tests/SoapClientBuilderTest.php index c61e7d7..344588c 100644 --- a/src/BeSimple/SoapClient/Tests/SoapClientBuilderTest.php +++ b/src/BeSimple/SoapClient/Tests/SoapClientBuilderTest.php @@ -22,6 +22,7 @@ use BeSimple\SoapCommon\ClassMap; use BeSimple\SoapCommon\SoapOptions\SoapOptions; use BeSimple\SoapCommon\SoapOptionsBuilder; use Exception; +use SoapClient; use SoapHeader; class SoapClientBuilderTest extends \PHPUnit_Framework_TestCase @@ -30,6 +31,7 @@ class SoapClientBuilderTest extends \PHPUnit_Framework_TestCase const TEST_ENDPOINT_UK = 'http://www.webservicex.net/uklocation.asmx'; const TEST_REMOTE_WSDL_UK = 'http://www.webservicex.net/uklocation.asmx?WSDL'; const TEST_LOCAL_WSDL_UK = __DIR__.'/localWsdl.wsdl'; + const TEST_REMOTE_ENDPOINT_NOT_WORKING = 'http://www.nosuchserverexist.tld/doesnotexist.endpoint'; const TEST_REMOTE_WSDL_NOT_WORKING = 'http://www.nosuchserverexist.tld/doesnotexist.endpoint?wsdl'; const TEST_ENDPOINT_SWA = 'https://demo2815480.mockable.io/soap/testGenerator'; const TEST_REMOTE_WSDL_SWA = 'https://demo2815480.mockable.io/soap/testGenerator?WSDL'; @@ -101,7 +103,7 @@ class SoapClientBuilderTest extends \PHPUnit_Framework_TestCase $soapOptions ); - self::assertInstanceOf(\SoapClient::class, $soapClient); + self::assertInstanceOf(SoapClient::class, $soapClient); } public function testSoapCall() @@ -119,6 +121,53 @@ class SoapClientBuilderTest extends \PHPUnit_Framework_TestCase self::assertEquals(self::TEST_ENDPOINT_UK, $soapResponse->getLocation()); } + public function testSoapCallWithCustomEndpointValid() + { + $soapClient = $this->getSoapBuilder()->build( + SoapClientOptionsBuilder::createWithEndpointLocation(self::TEST_ENDPOINT_UK), + SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_UK) + ); + $getUKLocationByCountyRequest = new GetUKLocationByCounty(); + $getUKLocationByCountyRequest->County = 'London'; + $soapResponse = $soapClient->soapCall('GetUKLocationByCounty', [$getUKLocationByCountyRequest]); + + self::assertContains('Connection: close', $soapResponse->getTracingData()->getLastRequestHeaders()); + self::assertContains('County>LondongetTracingData()->getLastRequest()); + self::assertContains('GetUKLocationByCountyResult', $soapResponse->getContent()); + self::assertContains('', $soapResponse->getContent()); + self::assertEquals(self::TEST_ENDPOINT_UK, $soapResponse->getLocation()); + } + + public function testSoapCallWithKeepAliveTrue() + { + $soapClient = $this->getSoapBuilder()->build( + SoapClientOptionsBuilder::createWithEndpointLocation(self::TEST_ENDPOINT_UK), + SoapOptionsBuilder::createWithDefaultsKeepAlive(self::TEST_REMOTE_WSDL_UK) + ); + $getUKLocationByCountyRequest = new GetUKLocationByCounty(); + $getUKLocationByCountyRequest->County = 'London'; + $soapResponse = $soapClient->soapCall('GetUKLocationByCounty', [$getUKLocationByCountyRequest]); + + self::assertContains('Connection: Keep-Alive', $soapResponse->getTracingData()->getLastRequestHeaders()); + self::assertContains('County>LondongetTracingData()->getLastRequest()); + self::assertContains('GetUKLocationByCountyResult', $soapResponse->getContent()); + self::assertContains('', $soapResponse->getContent()); + self::assertEquals(self::TEST_ENDPOINT_UK, $soapResponse->getLocation()); + } + + public function testSoapCallWithCustomEndpointInvalidShouldFail() + { + $this->setExpectedException(Exception::class, 'Could not resolve host'); + + $soapClient = $this->getSoapBuilder()->build( + SoapClientOptionsBuilder::createWithEndpointLocation(self::TEST_REMOTE_ENDPOINT_NOT_WORKING), + SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_UK) + ); + $getUKLocationByCountyRequest = new GetUKLocationByCounty(); + $getUKLocationByCountyRequest->County = 'London'; + $soapClient->soapCall('GetUKLocationByCounty', [$getUKLocationByCountyRequest]); + } + public function testSoapCallWithCacheEndpointDownShouldFail() { $this->setExpectedException(Exception::class, 'Could not write WSDL cache file: Download failed with message'); diff --git a/src/BeSimple/SoapCommon/SoapOptionsBuilder.php b/src/BeSimple/SoapCommon/SoapOptionsBuilder.php index f2c9d8c..a72ec58 100644 --- a/src/BeSimple/SoapCommon/SoapOptionsBuilder.php +++ b/src/BeSimple/SoapCommon/SoapOptionsBuilder.php @@ -30,6 +30,14 @@ class SoapOptionsBuilder return self::createWithClassMap($wsdlFile, new ClassMap(), $wsdlCacheType, $wsdlCacheDir); } + public static function createWithDefaultsKeepAlive( + $wsdlFile, + $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, + $wsdlCacheDir = null + ) { + return self::createWithClassMapKeepAlive($wsdlFile, new ClassMap(), $wsdlCacheType, $wsdlCacheDir); + } + public static function createSwaWithClassMap( $wsdlFile, ClassMap $classMap, @@ -92,6 +100,38 @@ class SoapOptionsBuilder ); } + public static function createWithClassMapKeepAlive( + $wsdlFile, + ClassMap $classMap, + $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, + $wsdlCacheDir = null, + $attachmentType = null + ) { + if (!Cache::hasType($wsdlCacheType)) { + throw new InvalidArgumentException('Invalid cache type'); + } + if ($wsdlCacheType !== SoapOptions::SOAP_CACHE_TYPE_NONE) { + if ($wsdlCacheDir === null) { + throw new InvalidArgumentException('Cache dir must be set for this wsdl cache type'); + } + } + + return new SoapOptions( + SoapOptions::SOAP_VERSION_1_2, + SoapOptions::SOAP_ENCODING_UTF8, + SoapOptions::SOAP_CONNECTION_KEEP_ALIVE_ON, + new SoapFeatures([ + SoapFeatures::SINGLE_ELEMENT_ARRAYS + ]), + $wsdlFile, + $wsdlCacheType, + $wsdlCacheDir, + $classMap, + new TypeConverterCollection(), + $attachmentType + ); + } + public static function createWithClassMapV11( $wsdlFile, ClassMap $classMap,