Merge branch 'mse' into develop

This commit is contained in:
Mimir
2020-07-15 16:26:24 +02:00
committed by GitHub
30 changed files with 291 additions and 152 deletions

View File

@ -1,3 +1,4 @@
vendor/
composer.lock
phpunit.xml
.idea/

View File

@ -15,15 +15,17 @@ namespace BeSimple\SoapBundle\Controller;
use BeSimple\SoapBundle\Handler\ExceptionHandler;
use BeSimple\SoapBundle\Soap\SoapRequest;
use BeSimple\SoapBundle\Soap\SoapResponse;
use BeSimple\SoapBundle\WebServiceContext;
use BeSimple\SoapServer\SoapServerBuilder;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* @author Christian Kerl <christian-kerl@web.de>
@ -31,11 +33,7 @@ use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
*/
class SoapWebServiceController implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
private $container;
use ContainerAwareTrait;
/**
* @var \SoapServer
@ -60,27 +58,20 @@ class SoapWebServiceController implements ContainerAwareInterface
/**
* @var array
*/
private $headers = array();
/**
* {@inheritDoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
private $headers = [];
/**
* @return \BeSimple\SoapBundle\Soap\SoapResponse
*/
public function callAction($webservice)
{
$webServiceContext = $this->getWebServiceContext($webservice);
/** @var WebServiceContext $webServiceContext */
$webServiceContext = $this->getWebServiceContext($webservice);
$this->serviceBinder = $webServiceContext->getServiceBinder();
$this->soapRequest = SoapRequest::createFromHttpRequest($this->container->get('request_stack')->getCurrentRequest());
$this->soapServer = $webServiceContext
$this->soapServer = $webServiceContext
->getServerBuilder()
->withSoapVersion11()
->withHandler($this)
@ -98,19 +89,26 @@ class SoapWebServiceController implements ContainerAwareInterface
}
/**
* @return Symfony\Component\HttpFoundation\Response
* @return Response
*/
public function definitionAction($webservice)
{
$routeName = $webservice.'_webservice_call';
$result = $this->container->get('router')->getRouteCollection()->get($routeName);
if (null === $result) {
$routeName = '_webservice_call';
}
$response = new Response($this->getWebServiceContext($webservice)->getWsdlFileContent(
$this->container->get('router')->generate(
'_webservice_call',
array('webservice' => $webservice),
true
$routeName,
['webservice' => $webservice],
UrlGeneratorInterface::ABSOLUTE_URL
)
));
$request = $this->container->get('request');
/** @var Request $request */
$request = $this->container->get('request_stack')->getCurrentRequest();
$query = $request->query;
if ($query->has('wsdl') || $query->has('WSDL')) {
$request->setRequestFormat('wsdl');
@ -136,14 +134,14 @@ class SoapWebServiceController implements ContainerAwareInterface
throw new \LogicException(sprintf('The parameter "%s" is required in Request::$query parameter bag to generate the SoapFault.', '_besimple_soap_webservice'), null, $e);
}
$view = 'TwigBundle:Exception:'.($this->container->get('kernel')->isDebug() ? 'exception' : 'error').'.txt.twig';
$view = '@Twig/Exception/'.($this->container->get('kernel')->isDebug() ? 'exception' : 'error').'.txt.twig';
$code = $exception->getStatusCode();
$details = $this->container->get('templating')->render($view, array(
$details = $this->container->get('twig')->render($view, [
'status_code' => $code,
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
'exception' => $exception,
'logger' => $logger,
));
'exception' => $exception,
'logger' => $logger,
]);
$handler = new ExceptionHandler($exception, $details);
if ($soapFault = $request->query->get('_besimple_soap_fault')) {
@ -177,8 +175,8 @@ class SoapWebServiceController implements ContainerAwareInterface
* This method gets called once for every SOAP header the \SoapServer received
* and afterwards once for the called SOAP operation.
*
* @param string $method The SOAP header or SOAP operation name
* @param array $arguments
* @param string $method The SOAP header or SOAP operation name
* @param array $arguments
*
* @return mixed
*/
@ -235,7 +233,7 @@ class SoapWebServiceController implements ContainerAwareInterface
}
/**
* Set the SoapResponse
* Set the SoapResponse.
*
* @param Response $response A response to check and set
*
@ -252,7 +250,7 @@ class SoapWebServiceController implements ContainerAwareInterface
return $this->soapResponse = $response;
}
private function getWebServiceContext($webservice)
protected function getWebServiceContext($webservice)
{
$context = sprintf('besimple.soap.context.%s', $webservice);

View File

@ -12,7 +12,7 @@ namespace BeSimple\SoapBundle\Converter;
use BeSimple\SoapBundle\Soap\SoapRequest;
use BeSimple\SoapBundle\Soap\SoapResponse;
use BeSimple\SoapBundle\Util\String;
use BeSimple\SoapBundle\Util\BsString;
use BeSimple\SoapCommon\Converter\TypeConverterInterface;
/**
@ -40,7 +40,7 @@ class XopIncludeTypeConverter implements TypeConverterInterface
$ref = $include->getAttribute('href');
if (String::startsWith($ref, 'cid:')) {
if (BsString::startsWith($ref, 'cid:')) {
$cid = urldecode(substr($ref, 4));
return $request->getSoapAttachments()->get($cid)->getContent();

View File

@ -17,7 +17,7 @@ use BeSimple\SoapCommon\Cache;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@ -88,14 +88,14 @@ class BeSimpleSoapExtension extends Extension
}
foreach ($config as $client => $options) {
$definition = new DefinitionDecorator('besimple.soap.client.builder');
$definition = new ChildDefinition('besimple.soap.client.builder');
$container->setDefinition(sprintf('besimple.soap.client.builder.%s', $client), $definition);
$definition->replaceArgument(0, $options['wsdl']);
$defOptions = $container
->getDefinition('besimple.soap.client.builder')
->getArgument(1);
->getDefinition('besimple.soap.client.builder')
->getArgument(1);
foreach (array('cache_type', 'user_agent') as $key) {
if (isset($options[$key])) {
@ -135,7 +135,7 @@ class BeSimpleSoapExtension extends Extension
private function createClientClassmap($client, array $classmap, ContainerBuilder $container)
{
$definition = new DefinitionDecorator('besimple.soap.classmap');
$definition = new ChildDefinition('besimple.soap.classmap');
$container->setDefinition(sprintf('besimple.soap.classmap.%s', $client), $definition);
if (!empty($classmap)) {
@ -149,7 +149,7 @@ class BeSimpleSoapExtension extends Extension
private function createClient($client, ContainerBuilder $container)
{
$definition = new DefinitionDecorator('besimple.soap.client');
$definition = new ChildDefinition('besimple.soap.client');
$container->setDefinition(sprintf('besimple.soap.client.%s', $client), $definition);
if (3 === Kernel::MAJOR_VERSION) {
@ -168,7 +168,7 @@ class BeSimpleSoapExtension extends Extension
unset($config['binding']);
$contextId = 'besimple.soap.context.'.$config['name'];
$definition = new DefinitionDecorator('besimple.soap.context.'.$bindingSuffix);
$definition = new ChildDefinition('besimple.soap.context.'.$bindingSuffix);
$container->setDefinition($contextId, $definition);
if (isset($config['cache_type'])) {
@ -177,6 +177,7 @@ class BeSimpleSoapExtension extends Extension
$options = $container
->getDefinition('besimple.soap.context.'.$bindingSuffix)
->setPublic(true)
->getArgument(2);
$definition->replaceArgument(2, array_merge($options, $config));

View File

@ -13,8 +13,8 @@
namespace BeSimple\SoapBundle\Handler;
use BeSimple\SoapServer\Exception\ReceiverSoapFault;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\FlattenException;
/**
* @author Francis Besset <francis.besset@gmail.com>

View File

@ -1,18 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="_webservice_call" path="/{webservice}">
<route id="_webservice_call" path="/{webservice}" methods="POST">
<default key="_controller">BeSimpleSoapBundle:SoapWebService:Call</default>
<default key="_format">xml</default>
<requirement key="_method">POST</requirement>
</route>
<route id="_webservice_definition" path="/{webservice}">
<route id="_webservice_definition" path="/{webservice}" methods="GET">
<default key="_controller">BeSimpleSoapBundle:SoapWebService:Definition</default>
<default key="_format">xml</default>
<requirement key="_method">GET</requirement>
</route>
</routes>

View File

@ -19,7 +19,7 @@
</parameters>
<services>
<service id="besimple.soap.response" class="%besimple.soap.response.class%" />
<service id="besimple.soap.response" class="%besimple.soap.response.class%" public="true" />
<service id="besimple.soap.response.listener" class="%besimple.soap.response.listener.class%">
<tag name="kernel.event_listener" event="kernel.view" method="onKernelView" />
@ -96,6 +96,14 @@
<argument>dateTime</argument>
<argument>xsd:dateTime</argument>
</call>
<call method="addType">
<argument>base64Binary</argument>
<argument>xsd:base64Binary</argument>
</call>
<call method="addType">
<argument>hexBinary</argument>
<argument>xsd:hexBinary</argument>
</call>
</service>
</services>

View File

@ -0,0 +1,33 @@
<?php
/*
* This file is part of the BeSimpleSoapBundle.
*
* (c) Christian Kerl <christian-kerl@web.de>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\SoapBundle\ServiceBinding;
use BeSimple\SoapBundle\ServiceDefinition\Method;
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
/**
* @author Francis Besset <francis.besset@gmail.com>
*/
class DocumentLiteralWrappedRequestHeaderMessageBinder extends DocumentLiteralWrappedRequestMessageBinder
{
private $header;
public function setHeader($header)
{
$this->header = $header;
}
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
{
$headerDefinition = $messageDefinition->getHeaders()->get($this->header);
return [];
}
}

View File

@ -11,23 +11,24 @@
namespace BeSimple\SoapBundle\ServiceBinding;
use BeSimple\SoapBundle\ServiceDefinition\Method;
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
/**
* @author Christian Kerl <christian-kerl@web.de>
*/
class DocumentLiteralWrappedRequestMessageBinder implements MessageBinderInterface
{
public function processMessage(Method $messageDefinition, $message)
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
{
if (count($message) > 1) {
throw new \InvalidArgumentException();
}
$result = array();
$result = array();
$message = $message[0];
foreach ($messageDefinition->getArguments() as $argument) {
$result[$argument->getName()] = $message->{$argument->getName()};
foreach ($messageDefinition->getInput()->all() as $argument) {
$result[$argument->getName()] = $message;
}
return $result;

View File

@ -11,17 +11,15 @@
namespace BeSimple\SoapBundle\ServiceBinding;
use BeSimple\SoapBundle\ServiceDefinition\Method;
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
/**
* @author Christian Kerl <christian-kerl@web.de>
*/
class DocumentLiteralWrappedResponseMessageBinder implements MessageBinderInterface
{
public function processMessage(Method $messageDefinition, $message)
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
{
$result = new \stdClass();
$result->{$messageDefinition->getName().'Result'} = $message;
return $result;
return $message;
}
}

View File

@ -32,7 +32,10 @@ class RpcLiteralResponseMessageBinder implements MessageBinderInterface
{
$this->typeRepository = $typeRepository;
return $this->processType($messageDefinition->getOutput()->get('return')->getType(), $message);
$parts = $messageDefinition->getOutput()->all();
$part = array_shift($parts);
return $this->processType($part->getType(), $message);
}
private function processType($phpType, $message)

View File

@ -96,6 +96,7 @@ class AnnotationClassLoader extends Loader
}
$serviceReturn = $annotation->getPhpType();
$serviceXmlReturn = $annotation->getXmlType();
}
}
@ -116,7 +117,11 @@ class AnnotationClassLoader extends Loader
throw new \LogicException(sprintf('@Soap\Result non-existent for "%s".', $method->getName()));
}
$serviceMethod->setOutput($this->loadType($serviceReturn));
if (!isset($serviceXmlReturn) || !$serviceXmlReturn) {
$serviceXmlReturn = 'return';
}
$serviceMethod->setOutput($this->loadType($serviceReturn), $serviceXmlReturn);
$definition->addMethod($serviceMethod);
}

View File

@ -15,7 +15,7 @@ namespace BeSimple\SoapBundle\Util;
*
* @author Christian Kerl <christian-kerl@web.de>
*/
class String
class BsString
{
/**
* Checks if a string starts with a given string.

View File

@ -77,9 +77,8 @@ class Curl
if (isset($options['compression']) && !($options['compression'] & SOAP_COMPRESSION_ACCEPT)) {
curl_setopt($this->ch, CURLOPT_ENCODING, 'identity');
}
if (isset($options['connection_timeout'])) {
curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $options['connection_timeout']);
}
curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, 10);
if (isset($options['proxy_host'])) {
if (false !== $options['proxy_host']) {
@ -167,7 +166,6 @@ class Curl
private function execManualRedirect($redirects = 0)
{
if ($redirects > $this->followLocationMaxRedirects) {
// TODO Redirection limit reached, aborting
return false;
}
@ -193,7 +191,7 @@ class Curl
if (!isset($url['path'])) {
$url['path'] = $lastUrl['path'];
}
$newUrl = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query'] ? '?' . $url['query'] : '');
$newUrl = $url['scheme'].'://'.$url['host'].$url['path'].($url['query'] ? '?'.$url['query'] : '');
curl_setopt($this->ch, CURLOPT_URL, $newUrl);
return $this->execManualRedirect($redirects++);
@ -205,7 +203,7 @@ class Curl
/**
* Error code mapping from cURL error codes to PHP ext/soap error messages
* (where applicable)
* (where applicable).
*
* http://curl.haxx.se/libcurl/c/libcurl-errors.html
*

View File

@ -24,7 +24,6 @@ abstract class AbstractWebServerTest extends \PHPUnit_Framework_TestCase
* @var ProcessBuilder
*/
protected static $webserver;
protected static $websererPortLength;
public static function setUpBeforeClass()
{
@ -44,8 +43,6 @@ abstract class AbstractWebServerTest extends \PHPUnit_Framework_TestCase
self::$webserver->start();
usleep(100000);
self::$websererPortLength = strlen(WEBSERVER_PORT);
}
public static function tearDownAfterClass()

View File

@ -45,19 +45,6 @@ class CurlTest extends AbstractWebserverTest
$this->assertEquals('Unable to parse URL', $curl->getErrorMessage());
}
public function testGetRequestHeaders()
{
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertEquals(132 + self::$websererPortLength, strlen($curl->getRequestHeaders()));
$curl->exec(sprintf('http://localhost:%s/404.txt', WEBSERVER_PORT));
$this->assertEquals(131 + self::$websererPortLength, strlen($curl->getRequestHeaders()));
}
public function testGetResponse()
{
$curl = new Curl(array(
@ -66,7 +53,6 @@ class CurlTest extends AbstractWebserverTest
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertSame('OK', $curl->getResponseStatusMessage());
$this->assertEquals(145 + self::$websererPortLength, strlen($curl->getResponse()));
$curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT));
$this->assertSame('Not Found', $curl->getResponseStatusMessage());
@ -95,19 +81,6 @@ class CurlTest extends AbstractWebserverTest
$this->assertEquals('text/html; charset=UTF-8', $curl->getResponseContentType());
}
public function testGetResponseHeaders()
{
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertEquals(117 + self::$websererPortLength, strlen($curl->getResponseHeaders()));
$curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT));
$this->assertEquals(124 + self::$websererPortLength, strlen($curl->getResponseHeaders()));
}
public function testGetResponseStatusCode()
{
$curl = new Curl(array(

View File

@ -101,6 +101,20 @@ class WsdlDownloader
if ($responseSuccessfull) {
$response = $this->curl->getResponseBody();
libxml_use_internal_errors(true);
$doc = simplexml_load_string($response);
if (!$doc) {
$errors = libxml_get_errors();
if (count($errors)) {
throw new \Exception('There is something wrong with the WSDL file formatting. The file can\'t be downloaded to be cached.');
}
libxml_clear_errors();
}
if ($this->resolveRemoteIncludes) {
$this->resolveRemoteIncludes($response, $cacheFilePath, $wsdl);
} else {

View File

@ -12,8 +12,6 @@
namespace BeSimple\SoapCommon\Definition;
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
/**
* @author Francis Besset <francis.besset@gmail.com>
*/
@ -66,7 +64,7 @@ class Method
$this->input->add($name, $type);
}
public function setOutput($type)
public function setOutput($type, $name = 'return')
{
$this->output->add('return', $type);
}

View File

@ -5,7 +5,7 @@ namespace BeSimple\SoapCommon\Type\KeyValue;
use BeSimple\SoapBundle\ServiceDefinition\Annotation as Soap;
use BeSimple\SoapCommon\Type\AbstractKeyValue;
class Boolean extends AbstractKeyValue
class BsBoolean extends AbstractKeyValue
{
/**
* @Soap\ComplexType("boolean")

View File

@ -5,7 +5,7 @@ namespace BeSimple\SoapCommon\Type\KeyValue;
use BeSimple\SoapBundle\ServiceDefinition\Annotation as Soap;
use BeSimple\SoapCommon\Type\AbstractKeyValue;
class Float extends AbstractKeyValue
class BsFloat extends AbstractKeyValue
{
/**
* @Soap\ComplexType("float")

View File

@ -5,7 +5,7 @@ namespace BeSimple\SoapCommon\Type\KeyValue;
use BeSimple\SoapBundle\ServiceDefinition\Annotation as Soap;
use BeSimple\SoapCommon\Type\AbstractKeyValue;
class Int extends AbstractKeyValue
class BsInt extends AbstractKeyValue
{
/**
* @Soap\ComplexType("int")

View File

@ -5,7 +5,7 @@ namespace BeSimple\SoapCommon\Type\KeyValue;
use BeSimple\SoapBundle\ServiceDefinition\Annotation as Soap;
use BeSimple\SoapCommon\Type\AbstractKeyValue;
class String extends AbstractKeyValue
class BsString extends AbstractKeyValue
{
/**
* @Soap\ComplexType("string")

View File

@ -30,7 +30,7 @@ abstract class WsSecurityFilterClientServer
/**
* The date format to be used with {@link \DateTime}
*/
const DATETIME_FORMAT = 'Y-m-d\TH:i:s.000\Z';
const DATETIME_FORMAT = 'Y-m-d\TH:i:s.u\Z';
/**
* (X509 3.2.1) Reference to a Subject Key Identifier

View File

@ -25,8 +25,7 @@
"ass/xmlsecurity": "~1.0"
},
"require-dev": {
"ext-mcrypt": "*",
"mikey179/vfsStream": "~1.0"
"mikey179/vfsstream": "~1.0"
},
"autoload": {
"psr-0": { "BeSimple\\SoapCommon": "" }

View File

@ -131,9 +131,7 @@ class SoapServer extends \SoapServer
/**
* Configure filter and type converter for SwA/MTOM.
*
* @param array &$options SOAP constructor options array.
*
* @return void
* @param array &$options SOAP constructor options array
*/
private function configureMime(array &$options)
{
@ -157,11 +155,11 @@ class SoapServer extends \SoapServer
}
$options['typemap'][] = array(
'type_name' => $converter->getTypeName(),
'type_ns' => $converter->getTypeNamespace(),
'from_xml' => function ($input) use ($converter) {
'type_ns' => $converter->getTypeNamespace(),
'from_xml' => function ($input) use ($converter) {
return $converter->convertXmlToPhp($input);
},
'to_xml' => function ($input) use ($converter) {
'to_xml' => function ($input) use ($converter) {
return $converter->convertPhpToXml($input);
},
);

View File

@ -86,7 +86,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque
$expires = $xpath->query($query, $security)->item(0);
if (null !== $expires) {
$expiresDatetime = \DateTime::createFromFormat(self::DATETIME_FORMAT, $expires->textContent, new \DateTimeZone('UTC'));
$expiresDatetime = \DateTime::createFromFormat(static::DATETIME_FORMAT, $expires->textContent, new \DateTimeZone('UTC'));
$currentDatetime = new \DateTime('now', new \DateTimeZone('UTC'));
if ($currentDatetime > $expiresDatetime) {
@ -170,7 +170,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque
// init timestamp
$dt = new \DateTime('now', new \DateTimeZone('UTC'));
$createdTimestamp = $dt->format(self::DATETIME_FORMAT);
$createdTimestamp = $dt->format(static::DATETIME_FORMAT);
// create security header
$security = $filterHelper->createElement(Helper::NS_WSS, 'Security');
@ -182,7 +182,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque
$timestamp->appendChild($created);
if (null !== $this->expires) {
$dt->modify('+' . $this->expires . ' seconds');
$expiresTimestamp = $dt->format(self::DATETIME_FORMAT);
$expiresTimestamp = $dt->format(static::DATETIME_FORMAT);
$expires = $filterHelper->createElement(Helper::NS_WSU, 'Expires', $expiresTimestamp);
$timestamp->appendChild($expires);
}