From ca33281678cd47cd7df6a426d3e69072e5e7fa83 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Mon, 8 Apr 2024 14:29:42 +0200 Subject: [PATCH] fix(ResponseType): Correctly add empty responses for 204/304 Signed-off-by: provokateurin --- src/ResponseType.php | 21 ++++- tests/appinfo/routes.php | 2 + tests/lib/Controller/SettingsController.php | 22 +++++ tests/openapi-administration.json | 94 +++++++++++++++++++++ tests/openapi-full.json | 94 +++++++++++++++++++++ 5 files changed, 230 insertions(+), 3 deletions(-) diff --git a/src/ResponseType.php b/src/ResponseType.php index 0fb06ff..7a1a152 100644 --- a/src/ResponseType.php +++ b/src/ResponseType.php @@ -258,14 +258,29 @@ public static function resolve(string $context, TypeNode $obj): array { $contentTypes = $contentTypes !== [] ? $contentTypes : [$type != null ? "*/*" : null]; foreach ($statusCodes as $statusCode) { - foreach ($contentTypes as $contentType) { + if ($statusCode === 204 || $statusCode === 304) { + $customHeaders = array_filter(array_keys($headers), static fn (string $header) => str_starts_with(strtolower($header), 'x-')); + if (!empty($customHeaders)) { + Logger::error($context, 'Custom headers are not allowed for responses with status code 204 or 304. Found: '. implode(', ', $customHeaders)); + } + $responses[] = new ControllerMethodResponse( $className, $statusCode, - $contentType, - $type, + null, + null, $headers, ); + } else { + foreach ($contentTypes as $contentType) { + $responses[] = new ControllerMethodResponse( + $className, + $statusCode, + $contentType, + $type, + $headers, + ); + } } } diff --git a/tests/appinfo/routes.php b/tests/appinfo/routes.php index 43b8e7b..7d86bf3 100644 --- a/tests/appinfo/routes.php +++ b/tests/appinfo/routes.php @@ -65,5 +65,7 @@ ['name' => 'Settings#arrayKeyedParameter', 'url' => '/api/{apiVersion}/array-keyed', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#throwingOCS', 'url' => '/api/{apiVersion}/throwing/ocs', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#throwingOther', 'url' => '/api/{apiVersion}/throwing/other', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#empty204', 'url' => '/api/{apiVersion}/204', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], + ['name' => 'Settings#empty304', 'url' => '/api/{apiVersion}/304', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ], ]; diff --git a/tests/lib/Controller/SettingsController.php b/tests/lib/Controller/SettingsController.php index 32ee004..c7e2e5b 100644 --- a/tests/lib/Controller/SettingsController.php +++ b/tests/lib/Controller/SettingsController.php @@ -439,4 +439,26 @@ public function throwingOCS(): DataResponse { public function throwingOther(): DataResponse { throw new NotFoundException(); } + + /** + * A route 204 response + * + * @return DataResponse, array{}> + * + * 204: No settings + */ + public function empty204(): DataResponse { + return new DataResponse(); + } + + /** + * A route 304 response + * + * @return DataResponse, array{}> + * + * 304: No settings + */ + public function empty304(): DataResponse { + return new DataResponse(); + } } diff --git a/tests/openapi-administration.json b/tests/openapi-administration.json index 7aa37bc..5eec96f 100644 --- a/tests/openapi-administration.json +++ b/tests/openapi-administration.json @@ -2328,6 +2328,100 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/204": { + "post": { + "operationId": "settings-empty204", + "summary": "A route 204 response", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "204": { + "description": "No settings" + } + } + } + }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/304": { + "post": { + "operationId": "settings-empty304", + "summary": "A route 304 response", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "304": { + "description": "No settings" + } + } + } + }, "/ocs/v2.php/tests/attribute-ocs/{param}": { "get": { "operationId": "routing-attributeocs-route", diff --git a/tests/openapi-full.json b/tests/openapi-full.json index 44d68b5..4b42bdb 100644 --- a/tests/openapi-full.json +++ b/tests/openapi-full.json @@ -2455,6 +2455,100 @@ } } }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/204": { + "post": { + "operationId": "settings-empty204", + "summary": "A route 204 response", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "204": { + "description": "No settings" + } + } + } + }, + "/ocs/v2.php/apps/notifications/api/{apiVersion}/304": { + "post": { + "operationId": "settings-empty304", + "summary": "A route 304 response", + "description": "This endpoint requires admin access", + "tags": [ + "settings" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "v2" + ], + "default": "v2" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "304": { + "description": "No settings" + } + } + } + }, "/ocs/v2.php/tests/attribute-ocs/{param}": { "get": { "operationId": "routing-attributeocs-route",