diff --git a/composer.json b/composer.json index 064e2d3..4a80a07 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,8 @@ "require": { "php": ">=8.1 <8.4", "ext-json": "*", - "byjg/webrequest": "^5.0" + "byjg/webrequest": "^5.0", + "byjg/xmlutil": "^5.0" }, "require-dev": { "phpunit/phpunit": "^9.6", diff --git a/src/AbstractRequester.php b/src/AbstractRequester.php index 7b61e88..12238a9 100644 --- a/src/AbstractRequester.php +++ b/src/AbstractRequester.php @@ -17,6 +17,7 @@ use ByJG\WebRequest\Exception\RequestException; use ByJG\WebRequest\Psr7\MemoryStream; use ByJG\WebRequest\Psr7\Request; +use ByJG\XmlUtil\XmlDocument; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -235,21 +236,28 @@ public function send(bool $matchQueryParams = true): ResponseInterface $this->psr7Request = $this->psr7Request->withUri($uri); // Prepare Body to Match Against Specification - $requestBody = $this->psr7Request->getBody()->getContents(); - if (!empty($requestBody)) { - $contentType = $this->psr7Request->getHeaderLine("content-type"); - if (empty($contentType) || str_contains($contentType, "application/json")) { - $requestBody = json_decode($requestBody, true); + $rawBody = $this->psr7Request->getBody()->getContents(); + $isXmlBody = false; + $requestBody = null; + $contentType = $this->psr7Request->getHeaderLine("content-type"); + if (!empty($rawBody)) { + if (str_contains($contentType, 'application/xml') || str_contains($contentType, 'text/xml')) { + $isXmlBody = new XmlDocument($rawBody); + } elseif (empty($contentType) || str_contains($contentType, "application/json")) { + $requestBody = json_decode($rawBody, true); } elseif (str_contains($contentType, "multipart/")) { - $requestBody = $this->parseMultiPartForm($contentType, $requestBody); + $requestBody = $this->parseMultiPartForm($contentType, $rawBody); } else { throw new InvalidRequestException("Cannot handle Content Type '$contentType'"); } + } // Check if the body is the expected before request - $bodyRequestDef = $this->schema->getRequestParameters($this->psr7Request->getUri()->getPath(), $this->psr7Request->getMethod(), $matchQueryParams ? $this->psr7Request->getUri()->getQuery() : null); - $bodyRequestDef->match($requestBody); + if ($isXmlBody === false) { + $bodyRequestDef = $this->schema->getRequestParameters($this->psr7Request->getUri()->getPath(), $this->psr7Request->getMethod(), $matchQueryParams ? $this->psr7Request->getUri()->getQuery() : null); + $bodyRequestDef->match($requestBody); + } // Handle Request $response = $this->handleRequest($this->psr7Request); diff --git a/tests/AbstractRequesterTest.php b/tests/AbstractRequesterTest.php index 42403e0..9bfc7fa 100644 --- a/tests/AbstractRequesterTest.php +++ b/tests/AbstractRequesterTest.php @@ -339,6 +339,45 @@ public function testValidateAssertBodyNotContains() $this->assertRequest($request); } + /** + * @throws DefinitionNotFoundException + * @throws GenericSwaggerException + * @throws HttpMethodNotFoundException + * @throws InvalidDefinitionException + * @throws InvalidRequestException + * @throws NotMatchedException + * @throws PathNotFoundException + * @throws RequiredArgumentNotFound + * @throws StatusCodeNotMatchedException + * @throws MessageException + * @throws RequestException + */ + public function testPostPetWithXmlBody() + { + $xmlBody = + '' . + 'Garfield XML' . + 'available' . + '' . + 'http://example.com/garfield.png' . + '' . + '' . + 'Cats' . + '' . + ''; + + $expectedResponse = Response::getInstance(200); + + $request = new MockRequester($expectedResponse); + $request + ->withMethod('POST') + ->withPath('/pet') + ->withRequestHeader(['Content-Type' => 'application/xml']) + ->withRequestBody($xmlBody); + + $this->assertRequest($request); + } + public function testMatchParameterInQueryAssert() { $expectedResponse = Response::getInstance(200)