Skip to content

Commit

Permalink
Multiple responses for same code in openapi (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
romanmatyus authored Apr 2, 2024
1 parent 0eb4d68 commit a581bc7
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 27 deletions.
67 changes: 40 additions & 27 deletions src/Handlers/OpenApiHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,33 +248,6 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath)
$handler = $api->getHandler();
$path = str_replace([$baseUrl, $basePath], '', $this->apiLink->link($api->getEndpoint()));
$responses = [];
foreach ($handler->outputs() as $output) {
if ($output instanceof JsonOutput) {
$schema = $this->transformSchema(json_decode($output->getSchema(), true));
$responses[$output->getCode()] = [
'description' => $output->getDescription(),
'content' => [
'application/json; charset=utf-8' => [
'schema' => $schema,
],
]
];
}

if ($output instanceof RedirectOutput) {
$responses[$output->getCode()] = [
'description' => 'Redirect',
'headers' => [
'Location' => [
'description' => $output->getDescription(),
'schema' => [
'type' => 'string',
]
],
]
];
}
}

$settings = [
'summary' => $handler->summary(),
Expand Down Expand Up @@ -328,6 +301,46 @@ private function getPaths(array $versionApis, string $baseUrl, string $basePath)
],
];

foreach ($handler->outputs() as $output) {
if ($output instanceof JsonOutput) {
$schema = $this->transformSchema(json_decode($output->getSchema(), true));
if (!isset($responses[$output->getCode()])) {
$responses[$output->getCode()] = [
'description' => $output->getDescription(),
'content' => [
'application/json; charset=utf-8' => [
'schema' => $schema,
],
]
];
} else {
if (!isset($responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'])) {
$tmp = $responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema'];
unset($responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']);
$responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema'] = [
'oneOf' => [],
];
$responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'][] = $tmp;
}
$responses[$output->getCode()]['content']['application/json; charset=utf-8']['schema']['oneOf'][] = $schema;
}
}

if ($output instanceof RedirectOutput) {
$responses[$output->getCode()] = [
'description' => 'Redirect',
'headers' => [
'Location' => [
'description' => $output->getDescription(),
'schema' => [
'type' => 'string',
]
],
]
];
}
}

if (!empty($parameters)) {
$settings['parameters'] = $parameters;
}
Expand Down
36 changes: 36 additions & 0 deletions tests/Handler/MultipleOutputTestHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Tomaj\NetteApi\Test\Handler;

use Tomaj\NetteApi\Handlers\BaseHandler;
use Tomaj\NetteApi\Output\JsonOutput;
use Tomaj\NetteApi\Response\JsonApiResponse;
use Tomaj\NetteApi\Response\ResponseInterface;

class MultipleOutputTestHandler extends BaseHandler
{
public function summary(): string
{
return 'Multiple output test handler';
}

public function description(): string
{
return 'This API handler is for test multiple ';
}

public function handle(array $params): ResponseInterface
{
return new JsonApiResponse(200, ['hello' => 'world']);
}

public function outputs(): array
{
return [
new JsonOutput(200, '{"type": "object"}'),
new JsonOutput(200, '{"type": "string"}'),
];
}
}
54 changes: 54 additions & 0 deletions tests/Handler/OpenApiHandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace Tomaj\NetteApi\Test\Handler;

use Nette\Application\LinkGenerator;
use Nette\Application\Routers\SimpleRouter;
use Nette\Http\UrlScript;
use PHPUnit\Framework\TestCase;
use Tomaj\NetteApi\ApiDecider;
use Tomaj\NetteApi\Authorization\NoAuthorization;
use Tomaj\NetteApi\EndpointIdentifier;
use Tomaj\NetteApi\Handlers\OpenApiHandler;
use Tomaj\NetteApi\Link\ApiLink;
use Nette\Http\Request;

class OpenApiHandlerTest extends TestCase
{
public function testHandlerWithMultipleResponseSchemas()
{
$linkGenerator = new LinkGenerator(new SimpleRouter([]), new UrlScript('http://test/'));
$apiLink = new ApiLink($linkGenerator);
$request = new Request(new UrlScript('http://test/'));

$apiDecider = new ApiDecider();
$apiDecider->addApi(
new EndpointIdentifier('GET', 1, 'test'),
new MultipleOutputTestHandler(),
new NoAuthorization()
);

$apiDecider->addApi(
new EndpointIdentifier('GET', 1, 'docs', 'open-api'),
new OpenApiHandler($apiDecider, $apiLink, $request),
new NoAuthorization()
);

$result = $apiDecider->getApi('GET', 1, 'docs', 'open-api');
$handler = $result->getHandler();

$response = $handler->handle(['format' => 'json']);
$this->assertEquals(200, $response->getCode());
$payload = $response->getPayload();

$this->assertEquals(2, count($payload['paths']));

$def = array_values($payload['paths'])[0]; // MultipleOutputTestHandler
$this->assertEquals(2, count($def['get']['responses'][200]['content']['application/json; charset=utf-8']['schema']['oneOf']));

$def = array_values($payload['paths'])[1]; // OpenApiHandler
$this->assertFalse(isset($def['get']['responses'][200]['content']['application/json; charset=utf-8']['schema']['oneOf']));
}
}

0 comments on commit a581bc7

Please sign in to comment.