Skip to content

Commit 3fb44c0

Browse files
committed
api: Document the item query parameter in the OpenAPI specs
The fallback added in this branch is a public API surface - `pi-hole/web#3818` uses `PUT /api/groups?item=...` as its regular edit path - but nothing described it. 1. `common.yaml` gains a shared `item` query parameter explaining why it exists (browsers collapse a `.`/`..` path segment) and that it is only consulted when the URI path carries no item. 2. `groups`, `clients`, `lists` and `domains` reference it on the operations that take an item, so it shows up on `GET`, `PUT` and `DELETE` alike. 3. Each of the four specs gains an `item_mismatch` example for the `400` returned when the path and the query name different items. We deliberately do not add `put`/`delete` to the item-less path objects (e.g., `/groups`): FTL reports its endpoints from a static table that lists those methods under `/groups/{name}`, and `test_all_endpoints_cross_check` compares the specs against that table in both directions. Signed-off-by: DL6ER <dl6er@dl6er.de>
1 parent 86cc14d commit 3fb44c0

5 files changed

Lines changed: 67 additions & 0 deletions

File tree

src/api/docs/content/specs/clients.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ components:
55
summary: Modify client
66
parameters:
77
- $ref: 'clients.yaml#/components/parameters/client'
8+
- $ref: 'common.yaml#/components/parameters/item'
89
get:
910
summary: Get clients
1011
tags:
@@ -75,6 +76,8 @@ components:
7576
examples:
7677
item_missing:
7778
$ref: 'clients.yaml#/components/examples/errors/uri_error/item_missing'
79+
item_mismatch:
80+
$ref: 'clients.yaml#/components/examples/errors/bad_request/item_mismatch'
7881
no_payload:
7982
$ref: 'clients.yaml#/components/examples/errors/bad_request/no_payload'
8083
duplicate:
@@ -114,6 +117,8 @@ components:
114117
examples:
115118
item_missing:
116119
$ref: 'clients.yaml#/components/examples/errors/uri_error/item_missing'
120+
item_mismatch:
121+
$ref: 'clients.yaml#/components/examples/errors/bad_request/item_mismatch'
117122
'401':
118123
description: Unauthorized
119124
content:
@@ -507,6 +512,14 @@ components:
507512
message: "Invalid request body data (no valid JSON)"
508513
hint: null
509514
took: 0.003
515+
item_mismatch:
516+
summary: URI path and "item" query parameter name different clients
517+
value:
518+
error:
519+
key: "bad_request"
520+
message: 'Invalid request: The item in the URI path and the "item" query parameter disagree'
521+
hint: "/api/clients/192.168.2.5"
522+
took: 0.003
510523
database_error:
511524
duplicate:
512525
summary: Database error

src/api/docs/content/specs/common.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,16 @@ components:
104104
type: boolean
105105
required: false
106106
example: false
107+
item:
108+
in: query
109+
name: item
110+
description: |
111+
The item to operate on, as an alternative to naming it in the URI path.
112+
113+
Browsers remove a path segment that is `.` or `..` - as well as their percent-encoded forms `%2e` and `%2e%2e` - while they resolve a URL, so an item with such a name can never reach Pi-hole as part of the path. A query parameter is not subject to this normalization, e.g., `PUT /api/groups?item=.`
114+
115+
The value is used whenever the URI path carries no item. Both may be given at the same time as long as they are identical: the path is what identifies the resource, so a disagreement is rejected with `400` instead of being silently resolved in favor of either one.
116+
schema:
117+
type: string
118+
required: false
119+
example: "."

src/api/docs/content/specs/domains.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ components:
5454
- $ref: 'domains.yaml#/components/parameters/type'
5555
- $ref: 'domains.yaml#/components/parameters/kind'
5656
- $ref: 'domains.yaml#/components/parameters/domain'
57+
- $ref: 'common.yaml#/components/parameters/item'
5758
get:
5859
operationId: "get_domain"
5960
<<: *get_path
@@ -107,6 +108,8 @@ components:
107108
$ref: 'domains.yaml#/components/examples/errors/uri_error/list_imprecise'
108109
item_missing:
109110
$ref: 'domains.yaml#/components/examples/errors/uri_error/item_missing'
111+
item_mismatch:
112+
$ref: 'domains.yaml#/components/examples/errors/bad_request/item_mismatch'
110113
no_payload:
111114
$ref: 'domains.yaml#/components/examples/errors/bad_request/no_payload'
112115
duplicate:
@@ -150,6 +153,8 @@ components:
150153
$ref: 'domains.yaml#/components/examples/errors/uri_error/list_imprecise'
151154
item_missing:
152155
$ref: 'domains.yaml#/components/examples/errors/uri_error/item_missing'
156+
item_mismatch:
157+
$ref: 'domains.yaml#/components/examples/errors/bad_request/item_mismatch'
153158
'401':
154159
description: Unauthorized
155160
content:
@@ -519,6 +524,14 @@ components:
519524
message: "Invalid request body data (no valid JSON)"
520525
hint: null
521526
took: 0.003
527+
item_mismatch:
528+
summary: URI path and "item" query parameter name different domains
529+
value:
530+
error:
531+
key: "bad_request"
532+
message: 'Invalid request: The item in the URI path and the "item" query parameter disagree'
533+
hint: "/api/domains/deny/exact/example.com"
534+
took: 0.003
522535
database_error:
523536
duplicate:
524537
summary: Database error

src/api/docs/content/specs/groups.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ components:
55
summary: Modify group
66
parameters:
77
- $ref: 'groups.yaml#/components/parameters/name'
8+
- $ref: 'common.yaml#/components/parameters/item'
89
get:
910
summary: Get groups
1011
tags:
@@ -77,6 +78,8 @@ components:
7778
examples:
7879
item_missing:
7980
$ref: 'groups.yaml#/components/examples/errors/uri_error/item_missing'
81+
item_mismatch:
82+
$ref: 'groups.yaml#/components/examples/errors/bad_request/item_mismatch'
8083
no_payload:
8184
$ref: 'groups.yaml#/components/examples/errors/bad_request/no_payload'
8285
duplicate:
@@ -116,6 +119,8 @@ components:
116119
examples:
117120
item_missing:
118121
$ref: 'groups.yaml#/components/examples/errors/uri_error/item_missing'
122+
item_mismatch:
123+
$ref: 'groups.yaml#/components/examples/errors/bad_request/item_mismatch'
119124
'401':
120125
description: Unauthorized
121126
content:
@@ -421,6 +426,14 @@ components:
421426
message: "Invalid request body data (no valid JSON)"
422427
hint: null
423428
took: 0.003
429+
item_mismatch:
430+
summary: URI path and "item" query parameter name different groups
431+
value:
432+
error:
433+
key: "bad_request"
434+
message: 'Invalid request: The item in the URI path and the "item" query parameter disagree'
435+
hint: "/api/groups/my_group"
436+
took: 0.003
424437
database_error:
425438
duplicate:
426439
summary: Database error

src/api/docs/content/specs/lists.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ components:
88
parameters:
99
- $ref: 'lists.yaml#/components/parameters/list'
1010
- $ref: 'lists.yaml#/components/parameters/listtype_optional'
11+
- $ref: 'common.yaml#/components/parameters/item'
1112
tags:
1213
- "List management"
1314
operationId: "get_lists"
@@ -42,6 +43,7 @@ components:
4243
parameters:
4344
- $ref: 'lists.yaml#/components/parameters/list'
4445
- $ref: 'lists.yaml#/components/parameters/listtype'
46+
- $ref: 'common.yaml#/components/parameters/item'
4547
tags:
4648
- "List management"
4749
operationId: "replace_lists"
@@ -77,6 +79,8 @@ components:
7779
examples:
7880
item_missing:
7981
$ref: 'lists.yaml#/components/examples/errors/uri_error/item_missing'
82+
item_mismatch:
83+
$ref: 'lists.yaml#/components/examples/errors/bad_request/item_mismatch'
8084
no_payload:
8185
$ref: 'lists.yaml#/components/examples/errors/bad_request/no_payload'
8286
duplicate:
@@ -94,6 +98,7 @@ components:
9498
parameters:
9599
- $ref: 'lists.yaml#/components/parameters/list'
96100
- $ref: 'lists.yaml#/components/parameters/listtype'
101+
- $ref: 'common.yaml#/components/parameters/item'
97102
tags:
98103
- "List management"
99104
operationId: "delete_lists"
@@ -120,6 +125,8 @@ components:
120125
examples:
121126
item_missing:
122127
$ref: 'lists.yaml#/components/examples/errors/uri_error/item_missing'
128+
item_mismatch:
129+
$ref: 'lists.yaml#/components/examples/errors/bad_request/item_mismatch'
123130
'401':
124131
description: Unauthorized
125132
content:
@@ -491,6 +498,14 @@ components:
491498
message: "Invalid request body data (no valid JSON)"
492499
hint: null
493500
took: 0.003
501+
item_mismatch:
502+
summary: URI path and "item" query parameter name different lists
503+
value:
504+
error:
505+
key: "bad_request"
506+
message: 'Invalid request: The item in the URI path and the "item" query parameter disagree'
507+
hint: "/api/lists/https://example.com/list.txt"
508+
took: 0.003
494509
database_error:
495510
duplicate:
496511
summary: Database error

0 commit comments

Comments
 (0)