Skip to content

Commit

Permalink
Pass SOAP 1.2 Action to XOP and use a valid cid identifier as startin…
Browse files Browse the repository at this point in the history
…g Content-Id
  • Loading branch information
veewee committed Jan 7, 2025
1 parent c71fe9c commit fc1a678
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 13 deletions.
19 changes: 15 additions & 4 deletions src/Multipart/RequestBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Psr\Http\Message\StreamFactoryInterface;
use Soap\Psr18AttachmentsMiddleware\Attachment\Attachment;
use Soap\Psr18AttachmentsMiddleware\Storage\AttachmentStorageInterface;
use Soap\Psr18Transport\HttpBinding\SoapActionDetector;
use function Psl\Result\try_catch;

final readonly class RequestBuilder implements RequestBuilderInterface
{
Expand Down Expand Up @@ -38,14 +40,23 @@ public function __invoke(

$builder = new MultipartStreamBuilder($this->streamFactory);

$contentTypeAction = '';
if ($attachmentType === AttachmentType::Mtom) {
$contentTypeAction = try_catch(
static fn () => SoapActionDetector::detectFromRequest($request),
static fn () => '',
);
$contentTypeAction = $contentTypeAction ? '; action=\"'.$contentTypeAction.'\"' : '';
}

$builder->addData(
(string) $request->getBody(),
[
'Content-Type' => match ($attachmentType) {
AttachmentType::Swa => 'text/xml; charset=UTF-8',
AttachmentType::Mtom => 'application/xop+xml; charset=UTF-8; type=application/soap+xml',
AttachmentType::Mtom => 'application/xop+xml; charset=UTF-8; type="application/soap+xml'.$contentTypeAction.'"',
},
'Content-ID' => 'soaprequest'
'Content-ID' => '<soaprequest@main>'
]
);

Expand Down Expand Up @@ -73,8 +84,8 @@ public function __invoke(
$request->getUri(),
)
->withAddedHeader('Content-Type', match($attachmentType) {
AttachmentType::Swa => 'multipart/related; type="text/xml"; boundary="' . $boundary. '"; start="soaprequest"',
AttachmentType::Mtom => 'multipart/related; type="application/xop+xml"; boundary="' . $boundary . '"; start="soaprequest"; start-info="application/soap+xml"',
AttachmentType::Swa => 'multipart/related; type="text/xml"; boundary="' . $boundary. '"; start="<soaprequest@main>"',
AttachmentType::Mtom => 'multipart/related; type="application/xop+xml"; boundary="' . $boundary . '"; start="<soaprequest@main>"; start-info="application/soap+xml'.$contentTypeAction.'"',
})
->withBody(
$builder->build()
Expand Down
6 changes: 3 additions & 3 deletions tests/Unit/Middleware/AttachmentsMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ public function it_can_attach_attachments(): void
$mockClient->setDefaultResponse(
Psr17FactoryDiscovery::findResponseFactory()
->createResponse(200)
->withAddedHeader('Content-Type', 'multipart/related; type="text/xml"; boundary="' . $boundary. '"; start="soaprequest"')
->withAddedHeader('Content-Type', 'multipart/related; type="text/xml"; boundary="' . $boundary. '"; start="<soaprequest@main>"')
->withBody(Psr17FactoryDiscovery::findStreamFactory()->createStream(
<<<EORESPONSE
--{$boundary}
Content-Type: text/xml; charset=UTF-8
Content-ID: soaprequest
Content-ID: <soaprequest@main>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
Expand Down Expand Up @@ -71,7 +71,7 @@ public function it_can_attach_attachments(): void
);
$requestContentType = $mockClient->getLastRequest()->getHeaderLine('Content-Type');
static::assertStringContainsString('multipart/related; type="text/xml";', $requestContentType);
static::assertStringContainsString('start="soaprequest"', $requestContentType);
static::assertStringContainsString('start="<soaprequest@main>"', $requestContentType);
static::assertCount(0, $storage->requestAttachments());
static::assertCount(1, $storage->responseAttachments());
static::assertSame(
Expand Down
54 changes: 48 additions & 6 deletions tests/Unit/Multipart/RequestBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function it_can_build_swa_related_multipart(): void
$expectedPayload = <<<EOF
--{$boundary}
Content-Type: text/xml; charset=UTF-8
Content-ID: soaprequest
Content-ID: <soaprequest@main>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
Expand All @@ -67,13 +67,13 @@ public function it_can_build_swa_related_multipart(): void
EOF;

static::assertSame($soapAction, $multipartRequest->getHeaderLine('SoapAction'));
static::assertSame('multipart/related; type="text/xml"; boundary="' . $boundary. '"; start="soaprequest"', $contentType);
static::assertSame('multipart/related; type="text/xml"; boundary="' . $boundary. '"; start="<soaprequest@main>"', $contentType);
static::assertSame(self::crlf($expectedPayload), (string) $multipartRequest->getBody());
}


#[Test]
public function it_can_build_mtom_related_multipart(): void
public function it_can_build_mtom_related_multipart_with_explicit_soap_action_info(): void
{
$storage = $this->createAttachmentsStore();
$requestBuilder = RequestBuilder::default();
Expand All @@ -86,8 +86,8 @@ public function it_can_build_mtom_related_multipart(): void

$expectedPayload = <<<EOF
--{$boundary}
Content-Type: application/xop+xml; charset=UTF-8; type=application/soap+xml
Content-ID: soaprequest
Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml; action=\"foo\""
Content-ID: <soaprequest@main>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
Expand All @@ -110,7 +110,49 @@ public function it_can_build_mtom_related_multipart(): void
EOF;

static::assertSame('multipart/related; type="application/xop+xml"; boundary="'.$boundary.'"; start="soaprequest"; start-info="application/soap+xml"', $contentType);
static::assertSame('multipart/related; type="application/xop+xml"; boundary="'.$boundary.'"; start="<soaprequest@main>"; start-info="application/soap+xml; action=\"foo\""', $contentType);
static::assertSame(self::crlf($expectedPayload), (string) $multipartRequest->getBody());
}

#[Test]
public function it_can_build_mtom_related_multipart_without_soap_action_info(): void
{
$storage = $this->createAttachmentsStore();
$requestBuilder = RequestBuilder::default();
$request = self::createSoapRequest()
->withAddedHeader('Content-Type', 'application/soap+xml');

$multipartRequest = $requestBuilder($request, $storage, AttachmentType::Mtom);
$contentType = $multipartRequest->getHeaderLine('Content-Type');
$boundary = StreamedPart::getHeaderOption($contentType, 'boundary');

$expectedPayload = <<<EOF
--{$boundary}
Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml"
Content-ID: <soaprequest@main>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"/>
</SOAP-ENV:Envelope>
--{$boundary}
Content-ID: attachment1
Content-Type: text/plain
Content-Disposition: attachment; name="file1"; filename="attachment1.txt"
Content-Transfer-Encoding: binary
attachment1
--{$boundary}
Content-ID: attachment2
Content-Type: text/plain
Content-Disposition: attachment; name="file2"; filename="attachment2.txt"
Content-Transfer-Encoding: binary
attachment2
--{$boundary}--
EOF;

static::assertSame('multipart/related; type="application/xop+xml"; boundary="'.$boundary.'"; start="<soaprequest@main>"; start-info="application/soap+xml"', $contentType);
static::assertSame(self::crlf($expectedPayload), (string) $multipartRequest->getBody());
}

Expand Down

0 comments on commit fc1a678

Please sign in to comment.