Skip to content

Commit

Permalink
Parse HTTP binding information
Browse files Browse the repository at this point in the history
  • Loading branch information
veewee committed Jan 20, 2025
1 parent ffb4e82 commit 21fa98a
Show file tree
Hide file tree
Showing 17 changed files with 300 additions and 27 deletions.
2 changes: 2 additions & 0 deletions src/Formatter/MetaTableFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Soap\WsdlReader\Formatter;

use Psl\Option\Option;
use ReflectionClass;
use ReflectionProperty;
use Symfony\Component\Console\Helper\Table;
Expand Down Expand Up @@ -58,6 +59,7 @@ private function tryStringifyValue(mixed $value): ?string
is_array($value) => json_encode($value, JSON_PRETTY_PRINT),
is_bool($value) => $value ? 'true' : 'false',
is_scalar($value) => (string)$value,
$value instanceof Option => $value->map($this->tryStringifyValue(...))->unwrapOr(null),
default => null,
};
} catch (Throwable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);

namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding;

use Soap\Engine\Metadata\Model\Method;
use Soap\WsdlReader\Model\Definitions\Binding;
use function Psl\Fun\pipe;

final class BindingConfigurator
{
public function __invoke(Method $method, Binding $binding): Method
{
return pipe(
static fn (Method $method) => (new HttpBindingConfigurator())($method, $binding),
static fn (Method $method) => (new SoapBindingConfigurator())($method, $binding),
)($method);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding;

use Soap\Engine\Metadata\Model\Method;
use Soap\Engine\Metadata\Model\MethodMeta;
use Soap\WsdlReader\Model\Definitions\Binding;
use Soap\WsdlReader\Model\Definitions\Implementation\Binding\HttpBinding;

final class HttpBindingConfigurator
{
public function __invoke(Method $method, Binding $binding): Method
{
$implementation = $binding->implementation;
if (!$implementation instanceof HttpBinding) {
return $method;
}

return $method->withMeta(
static fn (MethodMeta $meta): MethodMeta => $meta
->withTransport($implementation->transport->value)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<?php
declare(strict_types=1);

namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator;
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding;

use Soap\Engine\Metadata\Model\Method;
use Soap\Engine\Metadata\Model\MethodMeta;
use Soap\WsdlReader\Model\Definitions\Binding;
use Soap\WsdlReader\Model\Definitions\Implementation\Binding\SoapBinding;

final class BindingConfigurator
final class SoapBindingConfigurator
{
public function __invoke(Method $method, Binding $binding): Method
{
Expand All @@ -19,7 +19,7 @@ public function __invoke(Method $method, Binding $binding): Method

return $method->withMeta(
static fn (MethodMeta $meta): MethodMeta => $meta
->withTransport($implementation->transport->value)
->withTransport($implementation->transport->value)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
declare(strict_types=1);

namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation;

use Soap\Engine\Metadata\Model\Method;
use Soap\Engine\Metadata\Model\MethodMeta;
use Soap\WsdlReader\Model\Definitions\BindingOperation;
use Soap\WsdlReader\Model\Definitions\BindingStyle;
use Soap\WsdlReader\Model\Definitions\BindingUse;
use Soap\WsdlReader\Model\Definitions\EncodingStyle;
use Soap\WsdlReader\Model\Definitions\Implementation\Message\HttpMessage;
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\HttpOperation;
use Soap\WsdlReader\Model\Definitions\SoapVersion;

final class HttpBindingOperationConfigurator
{
public function __invoke(Method $method, BindingOperation $operation): Method
{
$implementation = $operation->implementation;
if (!$implementation instanceof HttpOperation) {
return $method;
}

if (!$this->messageIsConsideredSoap($operation)) {
return $method;
}

$guessedSoapVersion = $implementation->transport->guessSoapVersion();
$guessedBindingUse = $this->guessBindingUse($guessedSoapVersion);
$guessedEncodingStyle = $this->guessEncodingStyle($guessedSoapVersion);

return $method->withMeta(
static fn (MethodMeta $meta): MethodMeta => $meta
->withSoapVersion($guessedSoapVersion?->value)
->withAction('') // Soap Action is considered empty for HTTP binding.
->withOperationName($operation->name)
->withBindingStyle(BindingStyle::RPC->value)
->withInputBindingUsage($guessedBindingUse?->value)
->withInputEncodingStyle($guessedEncodingStyle?->value)
->withOutputBindingUsage($guessedBindingUse?->value)
->withOutputEncodingStyle($guessedEncodingStyle?->value)
);
}

private function messageIsConsideredSoap(BindingOperation $operation): bool
{
$input = $operation->input?->implementation;
if (!$input instanceof HttpMessage) {
return false;
}

return $input->isConsideredSoapContentType();
}

private function guessEncodingStyle(?SoapVersion $soapVersion): ?EncodingStyle
{
return match ($soapVersion) {
SoapVersion::SOAP_11 => EncodingStyle::SOAP_11,
SoapVersion::SOAP_12 => EncodingStyle::SOAP_12_2003_05,
default => null,
};
}

private function guessBindingUse(?SoapVersion $soapVersion): ?BindingUse
{
return match ($soapVersion) {
SoapVersion::SOAP_11 => BindingUse::ENCODED,
SoapVersion::SOAP_12 => BindingUse::LITERAL,
default => null,
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php declare(strict_types=1);

namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation;

use Soap\Engine\Metadata\Model\Method;
use Soap\WsdlReader\Model\Definitions\BindingOperation;
use function Psl\Fun\pipe;

final readonly class OperationConfigurator
{
public function __invoke(Method $method, BindingOperation $operation): Method
{
return pipe(
static fn (Method $method) => (new HttpBindingOperationConfigurator())($method, $operation),
static fn (Method $method) => (new SoapBindingOperationConfigurator())($method, $operation),
)($method);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);

namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator;
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation;

use Soap\Engine\Metadata\Model\Method;
use Soap\Engine\Metadata\Model\MethodMeta;
Expand All @@ -10,7 +10,7 @@
use Soap\WsdlReader\Model\Definitions\Implementation\Message\SoapMessage;
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\SoapOperation;

final class BindingOperationConfigurator
final class SoapBindingOperationConfigurator
{
public function __invoke(Method $method, BindingOperation $operation): Method
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ final class Wsdl1Configurator
{
public function __invoke(Method $method, Wsdl1 $wsdl): Method
{
$targetNamespace = $wsdl->targetNamespace?->value();

return $method->withMeta(
static fn (MethodMeta $meta): MethodMeta => $meta
->withTargetNamespace($wsdl->targetNamespace?->value())
->withTargetNamespace($targetNamespace)
->withInputNamespace($targetNamespace)
->withOutputNamespace($targetNamespace)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator;

use Soap\Engine\Metadata\Model\Method;
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding\BindingConfigurator;
use Soap\WsdlReader\Model\Service\Wsdl1SelectedService;
use function Psl\Fun\pipe;

Expand Down
4 changes: 2 additions & 2 deletions src/Metadata/Converter/Wsdl1ToMethodsConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Soap\Engine\Metadata\Model\Parameter;
use Soap\Engine\Metadata\Model\XsdType;
use Soap\WsdlReader\Locator\Wsdl1SelectedServiceLocator;
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\BindingOperationConfigurator;
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation\OperationConfigurator;
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\PortTypeOperationConfigurator;
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Wsdl1SelectedServiceConfigurator;
use Soap\WsdlReader\Metadata\Converter\Methods\Converter\MessageToMetadataTypesConverter;
Expand Down Expand Up @@ -66,7 +66,7 @@ private function parseMethod(Wsdl1SelectedService $service, BindingOperation $bi

$configure = pipe(
static fn (Method $method) => (new Wsdl1SelectedServiceConfigurator())($method, $service),
static fn (Method $method) => (new BindingOperationConfigurator())($method, $bindingOperation),
static fn (Method $method) => (new OperationConfigurator())($method, $bindingOperation),
static fn (Method $method) => (new PortTypeOperationConfigurator())($method, $portTypeOperation),
);

Expand Down
2 changes: 1 addition & 1 deletion src/Model/Definitions/AddressBindingType.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enum AddressBindingType : string
case SOAP_12 = 'http://schemas.xmlsoap.org/wsdl/soap12/';
case RPC = 'http://www.w3.org/2003/05/soap-rpc"';
case HTTP_11 = 'http://schemas.xmlsoap.org/wsdl/http/';
case HTTP_12 = 'http://www.w3.org/2003/05/soap/bindings/HTTP/"';
case HTTP_12 = 'http://www.w3.org/2003/05/soap/bindings/HTTP/';

public function isSoap(): bool
{
Expand Down
3 changes: 3 additions & 0 deletions src/Model/Definitions/Implementation/Binding/HttpBinding.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

namespace Soap\WsdlReader\Model\Definitions\Implementation\Binding;

use Soap\WsdlReader\Model\Definitions\TransportType;

final class HttpBinding implements BindingImplementation
{
public function __construct(
public readonly string $verb,
public readonly TransportType $transport,
) {
}
}
30 changes: 15 additions & 15 deletions src/Model/Definitions/Implementation/Message/HttpMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

final class HttpMessage implements MessageImplementation
{
// TODO ...
/*
* <wsdl:input>
<mime:content type="application/x-www-form-urlencoded"/>
</wsdl:input>
<wsdl:output>
<mime:mimeXml part="getServiceTicketResponsePart"/>
</wsdl:output>
public function __construct(
public readonly string $contentType,
public readonly ?string $part,
) {
}

<wsdl:input>
<http:urlEncoded/>
</wsdl:input>
<wsdl:output>
<mime:content part="ticket" type="text/plain"/>
</wsdl:output>
*/
public function isConsideredSoapContentType(): bool
{
return match(mb_strtolower($this->contentType)) {
'application/xml' => true,
'application/text' => true,
'application/soap+xml' => true,
'multipart/related' => true,
default => false,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

namespace Soap\WsdlReader\Model\Definitions\Implementation\Operation;

use Soap\WsdlReader\Model\Definitions\TransportType;

final class HttpOperation implements OperationImplementation
{
public function __construct(
public readonly string $location,
public readonly TransportType $transport,
) {
}
}
9 changes: 9 additions & 0 deletions src/Model/Definitions/TransportType.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,13 @@ public function isHttp(): bool
{
return $this === self::HTTP || $this === self::W3_HTTP;
}

public function guessSoapVersion(): ?SoapVersion
{
return match ($this) {
self::HTTP, self::SMTP => SoapVersion::SOAP_11,
self::W3_HTTP => SoapVersion::SOAP_12,
default => null,
};
}
}
38 changes: 35 additions & 3 deletions src/Parser/Strategy/HttpStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,58 @@
use Soap\WsdlReader\Model\Definitions\Implementation\Message\MessageImplementation;
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\HttpOperation;
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\OperationImplementation;
use Soap\WsdlReader\Model\Definitions\TransportType;
use VeeWee\Xml\Dom\Document;
use function VeeWee\Xml\Dom\Locator\Element\children;

final class HttpStrategy implements StrategyInterface
{
private const HTTP_NAMESPACE = 'http://schemas.xmlsoap.org/wsdl/http/';
private const MIME_NAMESPACE = 'http://schemas.xmlsoap.org/wsdl/mime/';

public function parseBindingImplementation(Document $wsdl, DOMElement $binding): BindingImplementation
{
return new HttpBinding(
verb: $binding->getAttribute('verb')
verb: $binding->getAttribute('verb'),
transport: TransportType::tryFrom((string) $binding->namespaceURI) ?? TransportType::HTTP,
);
}

public function parseOperationImplementation(Document $wsdl, DOMElement $operation): OperationImplementation
{
return new HttpOperation(
location: $operation->getAttribute('location')
location: $operation->getAttribute('location'),
transport: TransportType::tryFrom((string) $operation->namespaceURI) ?? TransportType::HTTP,
);
}

public function parseMessageImplementation(Document $wsdl, DOMElement $message): MessageImplementation
{
return new HttpMessage();
$info = children($message)->first();
$fallbackImplementation = new HttpMessage(
contentType: 'application/xml',
part: null
);

if (!$info) {
return $fallbackImplementation;
}

return match ($info->namespaceURI) {
self::HTTP_NAMESPACE => new HttpMessage(
contentType: 'text/plain',
part: null
),
self::MIME_NAMESPACE => new HttpMessage(
contentType: match($info->localName) {
'content' => $info->hasAttribute('type') ? $info->getAttribute('type'): 'application/xml',
'mimeXml' => 'application/xml',
'multipartRelated' => 'Multipart/Related',
default => 'application/xml'
},
part: $info->hasAttribute('part') ? $info->getAttribute('part') : null,
),
default => $fallbackImplementation,
};
}
}
Loading

0 comments on commit 21fa98a

Please sign in to comment.