Skip to content

Commit ecf189d

Browse files
Merge pull request #111 from nextcloud/fix/responsetype/empty-responses
2 parents ae84659 + 608a037 commit ecf189d

File tree

5 files changed

+232
-3
lines changed

5 files changed

+232
-3
lines changed

src/ResponseType.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,31 @@ public static function resolve(string $context, TypeNode $obj): array {
258258
$contentTypes = $contentTypes !== [] ? $contentTypes : [$type != null ? "*/*" : null];
259259

260260
foreach ($statusCodes as $statusCode) {
261-
foreach ($contentTypes as $contentType) {
261+
if ($statusCode === 204 || $statusCode === 304) {
262+
if ($statusCode === 304) {
263+
$customHeaders = array_filter(array_keys($headers), static fn (string $header) => str_starts_with(strtolower($header), 'x-'));
264+
if (!empty($customHeaders)) {
265+
Logger::error($context, 'Custom headers are not allowed for responses with status code 204 or 304. Found: ' . implode(', ', $customHeaders));
266+
}
267+
}
268+
262269
$responses[] = new ControllerMethodResponse(
263270
$className,
264271
$statusCode,
265-
$contentType,
266-
$type,
272+
null,
273+
null,
267274
$headers,
268275
);
276+
} else {
277+
foreach ($contentTypes as $contentType) {
278+
$responses[] = new ControllerMethodResponse(
279+
$className,
280+
$statusCode,
281+
$contentType,
282+
$type,
283+
$headers,
284+
);
285+
}
269286
}
270287
}
271288

tests/appinfo/routes.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,7 @@
6565
['name' => 'Settings#arrayKeyedParameter', 'url' => '/api/{apiVersion}/array-keyed', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
6666
['name' => 'Settings#throwingOCS', 'url' => '/api/{apiVersion}/throwing/ocs', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
6767
['name' => 'Settings#throwingOther', 'url' => '/api/{apiVersion}/throwing/other', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
68+
['name' => 'Settings#empty204', 'url' => '/api/{apiVersion}/204', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
69+
['name' => 'Settings#empty304', 'url' => '/api/{apiVersion}/304', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']],
6870
],
6971
];

tests/lib/Controller/SettingsController.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,26 @@ public function throwingOCS(): DataResponse {
439439
public function throwingOther(): DataResponse {
440440
throw new NotFoundException();
441441
}
442+
443+
/**
444+
* A route 204 response
445+
*
446+
* @return DataResponse<Http::STATUS_NO_CONTENT, array<empty>, array{}>
447+
*
448+
* 204: No settings
449+
*/
450+
public function empty204(): DataResponse {
451+
return new DataResponse();
452+
}
453+
454+
/**
455+
* A route 304 response
456+
*
457+
* @return DataResponse<Http::STATUS_NOT_MODIFIED, array<empty>, array{}>
458+
*
459+
* 304: No settings
460+
*/
461+
public function empty304(): DataResponse {
462+
return new DataResponse();
463+
}
442464
}

tests/openapi-administration.json

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,6 +2328,100 @@
23282328
}
23292329
}
23302330
},
2331+
"/ocs/v2.php/apps/notifications/api/{apiVersion}/204": {
2332+
"post": {
2333+
"operationId": "settings-empty204",
2334+
"summary": "A route 204 response",
2335+
"description": "This endpoint requires admin access",
2336+
"tags": [
2337+
"settings"
2338+
],
2339+
"security": [
2340+
{
2341+
"bearer_auth": []
2342+
},
2343+
{
2344+
"basic_auth": []
2345+
}
2346+
],
2347+
"parameters": [
2348+
{
2349+
"name": "apiVersion",
2350+
"in": "path",
2351+
"required": true,
2352+
"schema": {
2353+
"type": "string",
2354+
"enum": [
2355+
"v2"
2356+
],
2357+
"default": "v2"
2358+
}
2359+
},
2360+
{
2361+
"name": "OCS-APIRequest",
2362+
"in": "header",
2363+
"description": "Required to be true for the API request to pass",
2364+
"required": true,
2365+
"schema": {
2366+
"type": "boolean",
2367+
"default": true
2368+
}
2369+
}
2370+
],
2371+
"responses": {
2372+
"204": {
2373+
"description": "No settings"
2374+
}
2375+
}
2376+
}
2377+
},
2378+
"/ocs/v2.php/apps/notifications/api/{apiVersion}/304": {
2379+
"post": {
2380+
"operationId": "settings-empty304",
2381+
"summary": "A route 304 response",
2382+
"description": "This endpoint requires admin access",
2383+
"tags": [
2384+
"settings"
2385+
],
2386+
"security": [
2387+
{
2388+
"bearer_auth": []
2389+
},
2390+
{
2391+
"basic_auth": []
2392+
}
2393+
],
2394+
"parameters": [
2395+
{
2396+
"name": "apiVersion",
2397+
"in": "path",
2398+
"required": true,
2399+
"schema": {
2400+
"type": "string",
2401+
"enum": [
2402+
"v2"
2403+
],
2404+
"default": "v2"
2405+
}
2406+
},
2407+
{
2408+
"name": "OCS-APIRequest",
2409+
"in": "header",
2410+
"description": "Required to be true for the API request to pass",
2411+
"required": true,
2412+
"schema": {
2413+
"type": "boolean",
2414+
"default": true
2415+
}
2416+
}
2417+
],
2418+
"responses": {
2419+
"304": {
2420+
"description": "No settings"
2421+
}
2422+
}
2423+
}
2424+
},
23312425
"/ocs/v2.php/tests/attribute-ocs/{param}": {
23322426
"get": {
23332427
"operationId": "routing-attributeocs-route",

tests/openapi-full.json

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,6 +2455,100 @@
24552455
}
24562456
}
24572457
},
2458+
"/ocs/v2.php/apps/notifications/api/{apiVersion}/204": {
2459+
"post": {
2460+
"operationId": "settings-empty204",
2461+
"summary": "A route 204 response",
2462+
"description": "This endpoint requires admin access",
2463+
"tags": [
2464+
"settings"
2465+
],
2466+
"security": [
2467+
{
2468+
"bearer_auth": []
2469+
},
2470+
{
2471+
"basic_auth": []
2472+
}
2473+
],
2474+
"parameters": [
2475+
{
2476+
"name": "apiVersion",
2477+
"in": "path",
2478+
"required": true,
2479+
"schema": {
2480+
"type": "string",
2481+
"enum": [
2482+
"v2"
2483+
],
2484+
"default": "v2"
2485+
}
2486+
},
2487+
{
2488+
"name": "OCS-APIRequest",
2489+
"in": "header",
2490+
"description": "Required to be true for the API request to pass",
2491+
"required": true,
2492+
"schema": {
2493+
"type": "boolean",
2494+
"default": true
2495+
}
2496+
}
2497+
],
2498+
"responses": {
2499+
"204": {
2500+
"description": "No settings"
2501+
}
2502+
}
2503+
}
2504+
},
2505+
"/ocs/v2.php/apps/notifications/api/{apiVersion}/304": {
2506+
"post": {
2507+
"operationId": "settings-empty304",
2508+
"summary": "A route 304 response",
2509+
"description": "This endpoint requires admin access",
2510+
"tags": [
2511+
"settings"
2512+
],
2513+
"security": [
2514+
{
2515+
"bearer_auth": []
2516+
},
2517+
{
2518+
"basic_auth": []
2519+
}
2520+
],
2521+
"parameters": [
2522+
{
2523+
"name": "apiVersion",
2524+
"in": "path",
2525+
"required": true,
2526+
"schema": {
2527+
"type": "string",
2528+
"enum": [
2529+
"v2"
2530+
],
2531+
"default": "v2"
2532+
}
2533+
},
2534+
{
2535+
"name": "OCS-APIRequest",
2536+
"in": "header",
2537+
"description": "Required to be true for the API request to pass",
2538+
"required": true,
2539+
"schema": {
2540+
"type": "boolean",
2541+
"default": true
2542+
}
2543+
}
2544+
],
2545+
"responses": {
2546+
"304": {
2547+
"description": "No settings"
2548+
}
2549+
}
2550+
}
2551+
},
24582552
"/ocs/v2.php/tests/attribute-ocs/{param}": {
24592553
"get": {
24602554
"operationId": "routing-attributeocs-route",

0 commit comments

Comments
 (0)