Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
ecffdc18fd | |||
b45202f40a | |||
ab83642f06 |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "tuscanicz/soap",
|
"name": "tuscanicz/soap",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"description": "A fork of the abandoned besimple/soap package with added support for Symfony 3.0",
|
"description": "A largely refactored besimple/soap used to build SOAP and WSDL based web services. This fork fixes a lot of errors and provides better API, robust, stable and modern codebase.",
|
||||||
"keywords": ["soap", "soap server", "soap client"],
|
"keywords": ["soap", "soap server", "soap client"],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"authors": [
|
||||||
|
@ -318,14 +318,14 @@ class SoapClient extends \SoapClient
|
|||||||
} else if ($curlResponse->curlStatusFailed()) {
|
} else if ($curlResponse->curlStatusFailed()) {
|
||||||
|
|
||||||
return $this->throwSoapFaultByTracing(
|
return $this->throwSoapFaultByTracing(
|
||||||
SoapFaultPrefixEnum::PREFIX_DEFAULT.'-'.SoapFaultEnum::SOAP_FAULT_HTTP.'-'.$curlResponse->getHttpResponseStatusCode(),
|
SoapFaultEnum::SOAP_FAULT_HTTP.'-'.$curlResponse->getHttpResponseStatusCode(),
|
||||||
$curlResponse->getCurlErrorMessage(),
|
$curlResponse->getCurlErrorMessage(),
|
||||||
$soapResponseTracingData
|
$soapResponseTracingData
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
return $this->throwSoapFaultByTracing(
|
return $this->throwSoapFaultByTracing(
|
||||||
SoapFaultPrefixEnum::PREFIX_DEFAULT.'-'.SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR,
|
SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR,
|
||||||
'Cannot process curl response with unresolved status: ' . $curlResponse->getCurlStatus(),
|
'Cannot process curl response with unresolved status: ' . $curlResponse->getCurlStatus(),
|
||||||
$soapResponseTracingData
|
$soapResponseTracingData
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,7 @@ namespace BeSimple\SoapCommon\Fault;
|
|||||||
|
|
||||||
class SoapFaultEnum
|
class SoapFaultEnum
|
||||||
{
|
{
|
||||||
const SOAP_FAULT_WSDL = 'wsdl';
|
const SOAP_FAULT_WSDL = SoapFaultPrefixEnum::PREFIX_DEFAULT.'-'.'wsdl';
|
||||||
const SOAP_FAULT_HTTP = 'http';
|
const SOAP_FAULT_HTTP = SoapFaultPrefixEnum::PREFIX_DEFAULT.'-'.'http';
|
||||||
const SOAP_FAULT_SOAP_CLIENT_ERROR = 'soap-client-error';
|
const SOAP_FAULT_SOAP_CLIENT_ERROR = SoapFaultPrefixEnum::PREFIX_DEFAULT.'-'.'soap-client-error';
|
||||||
}
|
}
|
||||||
|
@ -13,13 +13,13 @@ class SoapFaultSourceGetter
|
|||||||
|
|
||||||
public static function isBeSimpleSoapFault(SoapFault $soapFault)
|
public static function isBeSimpleSoapFault(SoapFault $soapFault)
|
||||||
{
|
{
|
||||||
$defaultPrefix = SoapFaultPrefixEnum::PREFIX_DEFAULT;
|
$nativeSoapFaultPrefix = SoapFaultPrefixEnum::PREFIX_DEFAULT.'-';
|
||||||
|
|
||||||
if (strpos($soapFault->getCode(), $defaultPrefix) === 0) {
|
if (strpos($soapFault->faultcode, $nativeSoapFaultPrefix) === 0) {
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ class MimeBoundaryAnalyser
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @todo: This method is not reliable at all
|
||||||
* @param string $mimeMessageLine
|
* @param string $mimeMessageLine
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -29,25 +29,16 @@ class Parser
|
|||||||
/**
|
/**
|
||||||
* Parse the given Mime-Message and return a \BeSimple\SoapCommon\Mime\MultiPart object.
|
* Parse the given Mime-Message and return a \BeSimple\SoapCommon\Mime\MultiPart object.
|
||||||
*
|
*
|
||||||
* @param string $mimeMessage Mime message string
|
* @param string $mimeMessage Mime message string
|
||||||
* @param string[] $headers array(string=>string) of header elements (e.g. coming from http request)
|
* @param string[] $headers array(string=>string) of header elements (e.g. coming from http request)
|
||||||
*
|
* @return MultiPart
|
||||||
* @return \BeSimple\SoapCommon\Mime\MultiPart
|
|
||||||
*/
|
*/
|
||||||
public static function parseMimeMessage($mimeMessage, array $headers = [])
|
public static function parseMimeMessage($mimeMessage, array $headers = [])
|
||||||
{
|
{
|
||||||
$multiPart = new MultiPart();
|
$multiPart = new MultiPart();
|
||||||
$mimeMessageLines = explode("\n", $mimeMessage);
|
$mimeMessageLines = explode("\n", $mimeMessage);
|
||||||
$mimeMessageLineCount = count($mimeMessageLines);
|
$mimeMessageLineCount = count($mimeMessageLines);
|
||||||
if ($mimeMessageLineCount <= 1) {
|
|
||||||
throw new Exception(
|
|
||||||
sprintf(
|
|
||||||
'Cannot process message of %d characters: got unexpectable low number of lines: %s',
|
|
||||||
mb_strlen($mimeMessage),
|
|
||||||
(string)$mimeMessageLineCount
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// add given headers, e.g. coming from HTTP headers
|
// add given headers, e.g. coming from HTTP headers
|
||||||
if (count($headers) > 0) {
|
if (count($headers) > 0) {
|
||||||
self::setMultiPartHeaders($multiPart, $headers);
|
self::setMultiPartHeaders($multiPart, $headers);
|
||||||
@ -56,6 +47,15 @@ class Parser
|
|||||||
$hasHttpRequestHeaders = ParsedPartsGetter::HAS_NO_HTTP_REQUEST_HEADERS;
|
$hasHttpRequestHeaders = ParsedPartsGetter::HAS_NO_HTTP_REQUEST_HEADERS;
|
||||||
}
|
}
|
||||||
if (MimeBoundaryAnalyser::hasMessageBoundary($mimeMessageLines) === true) {
|
if (MimeBoundaryAnalyser::hasMessageBoundary($mimeMessageLines) === true) {
|
||||||
|
if ($mimeMessageLineCount <= 1) {
|
||||||
|
throw new Exception(
|
||||||
|
sprintf(
|
||||||
|
'Cannot parse MultiPart message of %d characters: got unexpectable low number of lines: %s',
|
||||||
|
mb_strlen($mimeMessage),
|
||||||
|
(string)$mimeMessageLineCount
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
$parsedPartList = ParsedPartsGetter::getPartsFromMimeMessageLines(
|
$parsedPartList = ParsedPartsGetter::getPartsFromMimeMessageLines(
|
||||||
$multiPart,
|
$multiPart,
|
||||||
$mimeMessageLines,
|
$mimeMessageLines,
|
||||||
|
@ -121,6 +121,7 @@ class SoapServerOptions
|
|||||||
{
|
{
|
||||||
$optionsAsArray = [
|
$optionsAsArray = [
|
||||||
'keep_alive' => $this->isKeepAlive(),
|
'keep_alive' => $this->isKeepAlive(),
|
||||||
|
'exceptions' => $this->isExceptions(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $optionsAsArray;
|
return $optionsAsArray;
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeSimple\SoapCommon\Fault;
|
||||||
|
|
||||||
|
use PHPUnit_Framework_TestCase;
|
||||||
|
use SoapFault;
|
||||||
|
|
||||||
|
class SoapFaultSourceGetterTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
const FIXTURES_DIR = __DIR__ . '/../../Fixtures';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SoapFault $soapFault
|
||||||
|
* @dataProvider provideNativeSoapFaults
|
||||||
|
*/
|
||||||
|
public function testWithNativeSoapFault(SoapFault $soapFault)
|
||||||
|
{
|
||||||
|
self::assertTrue(SoapFaultSourceGetter::isNativeSoapFault($soapFault));
|
||||||
|
self::assertFalse(SoapFaultSourceGetter::isBeSimpleSoapFault($soapFault));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SoapFault $soapFault
|
||||||
|
* @dataProvider provideBeSimpleSoapFaults
|
||||||
|
*/
|
||||||
|
public function testWithBeSimpleSoapFault(SoapFault $soapFault)
|
||||||
|
{
|
||||||
|
self::assertFalse(SoapFaultSourceGetter::isNativeSoapFault($soapFault));
|
||||||
|
self::assertTrue(SoapFaultSourceGetter::isBeSimpleSoapFault($soapFault));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideNativeSoapFaults()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[$this->getNativeSoapFaultFromClient()],
|
||||||
|
// @todo: add more test cases for Soap Server \SoapFault
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideBeSimpleSoapFaults()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[new SoapFault(SoapFaultEnum::SOAP_FAULT_HTTP, 'HTTP Connection error')],
|
||||||
|
[new SoapFault(SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR, 'SOAP Client error')],
|
||||||
|
[new SoapFault(SoapFaultEnum::SOAP_FAULT_WSDL, 'WSDL error')],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return SoapFault
|
||||||
|
*/
|
||||||
|
private function getNativeSoapFaultFromClient()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$soapClient = @new \SoapClient('non-existing-wsdl-throwing-soapfault');
|
||||||
|
$soapClient->__call('no-function', []);
|
||||||
|
} catch (SoapFault $e) {
|
||||||
|
|
||||||
|
return $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::fail('Cannot generate native PHP SoapFault from Client, please review the test');
|
||||||
|
}
|
||||||
|
}
|
99
tests/BeSimple/SoapCommon/Mime/ParserTest.php
Normal file
99
tests/BeSimple/SoapCommon/Mime/ParserTest.php
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeSimple\SoapCommon\Mime;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use PHPUnit_Framework_TestCase;
|
||||||
|
|
||||||
|
class ParserTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
const TEST_CASE_SHOULD_FAIL = true;
|
||||||
|
const TEST_CASE_SHOULD_NOT_FAIL = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideMimeMessages
|
||||||
|
* @param string $mimeMessage
|
||||||
|
* @param string[] $headers
|
||||||
|
* @param bool $testCaseShouldFail
|
||||||
|
* @param string|null $failedTestCaseFailMessage
|
||||||
|
*/
|
||||||
|
public function testParseMimeMessage(
|
||||||
|
$mimeMessage,
|
||||||
|
array $headers,
|
||||||
|
$testCaseShouldFail,
|
||||||
|
$failedTestCaseFailMessage = null
|
||||||
|
) {
|
||||||
|
if ($testCaseShouldFail === true) {
|
||||||
|
$this->setExpectedException(Exception::class, $failedTestCaseFailMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
$mimeMessage = Parser::parseMimeMessage($mimeMessage, $headers);
|
||||||
|
|
||||||
|
if ($testCaseShouldFail === false) {
|
||||||
|
self::assertInstanceOf(MultiPart::class, $mimeMessage);
|
||||||
|
self::assertInstanceOf(Part::class, $mimeMessage->getMainPart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideMimeMessages()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'ParseRequest' => [
|
||||||
|
$this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Request/dummyServiceMethod.message.request'),
|
||||||
|
[],
|
||||||
|
self::TEST_CASE_SHOULD_NOT_FAIL
|
||||||
|
],
|
||||||
|
'ParseRequestOneLiner' => [
|
||||||
|
$this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request'),
|
||||||
|
[],
|
||||||
|
self::TEST_CASE_SHOULD_NOT_FAIL
|
||||||
|
],
|
||||||
|
'ParseSwaResponseWith2FilesAnd1BinaryFile' => [
|
||||||
|
$this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'),
|
||||||
|
[
|
||||||
|
'Content-Type' => 'multipart/related;'.
|
||||||
|
' type="application/soap+xml"; charset=utf-8;'.
|
||||||
|
' boundary=Part_13_58e3bc35f3743.58e3bc35f376f;'.
|
||||||
|
' start="<part-424dbe68-e2da-450f-9a82-cc3e82742503@response.info>"'
|
||||||
|
],
|
||||||
|
self::TEST_CASE_SHOULD_NOT_FAIL
|
||||||
|
],
|
||||||
|
'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithNoHeaders' => [
|
||||||
|
$this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'),
|
||||||
|
[],
|
||||||
|
self::TEST_CASE_SHOULD_FAIL,
|
||||||
|
'Unable to get Content-Type boundary'
|
||||||
|
],
|
||||||
|
'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithWrongHeaders' => [
|
||||||
|
$this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'),
|
||||||
|
[
|
||||||
|
'Content-Type' => 'multipart/related; type="application/soap+xml"; charset=utf-8; boundary=DOES_NOT_EXIST; start="<non-existing>"'
|
||||||
|
],
|
||||||
|
self::TEST_CASE_SHOULD_FAIL,
|
||||||
|
'cannot parse headers before hitting the first boundary'
|
||||||
|
],
|
||||||
|
'ParseSwaRequestWith2Files' => [
|
||||||
|
$this->getMimeMessageFromFile(__DIR__ . '/../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'),
|
||||||
|
[
|
||||||
|
'Content-Type' => 'multipart/related; type="application/soap+xml"; charset=utf-8; boundary=----=_Part_6_2094841787.1482231370463; start="<rootpart@soapui.org>"'
|
||||||
|
],
|
||||||
|
self::TEST_CASE_SHOULD_NOT_FAIL
|
||||||
|
],
|
||||||
|
'ParseSwaRequestWith2FilesShouldFailWithNoHeaders' => [
|
||||||
|
$this->getMimeMessageFromFile(__DIR__ . '/../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'),
|
||||||
|
[],
|
||||||
|
self::TEST_CASE_SHOULD_FAIL,
|
||||||
|
'Unable to get Content-Type boundary'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getMimeMessageFromFile($filePath)
|
||||||
|
{
|
||||||
|
if (file_exists($filePath) === false) {
|
||||||
|
self::fail('Please, update tests data provider - file not found: '.$filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file_get_contents($filePath);
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,6 @@ class SoapServerAndSoapClientCommunicationTest extends PHPUnit_Framework_TestCas
|
|||||||
const CACHE_DIR = __DIR__ . '/../../cache';
|
const CACHE_DIR = __DIR__ . '/../../cache';
|
||||||
const FIXTURES_DIR = __DIR__ . '/../Fixtures';
|
const FIXTURES_DIR = __DIR__ . '/../Fixtures';
|
||||||
const TEST_HTTP_URL = 'http://localhost:8000/tests';
|
const TEST_HTTP_URL = 'http://localhost:8000/tests';
|
||||||
const TEST_LOCAL_WSDL_UK = SoapClientBuilderTest::TEST_LOCAL_WSDL_UK;
|
|
||||||
const LARGE_SWA_FILE = self::FIXTURES_DIR.'/large-test-file.docx';
|
const LARGE_SWA_FILE = self::FIXTURES_DIR.'/large-test-file.docx';
|
||||||
|
|
||||||
private $localWebServerProcess;
|
private $localWebServerProcess;
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://schema.testcase"><soapenv:Header><sch:SoapHeader><user>admin</user></sch:SoapHeader></soapenv:Header><soapenv:Body><sch:dummyServiceMethod><request><dummyAttribute>1</dummyAttribute></request></sch:dummyServiceMethod></soapenv:Body></soapenv:Envelope>
|
Reference in New Issue
Block a user