Skip to content

Commit 5eb0f11

Browse files
committed
feat(rules): add new configurable rule for deprecated operations
1 parent d155441 commit 5eb0f11

File tree

4 files changed

+421
-0
lines changed

4 files changed

+421
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ There are some fantastic examples of [configurable rules](https://redocly.com/do
4646
- [String schemas length defined](configurable-rules/string-schemas-length-defined/)
4747
- [JSON Schema misconfigurations](configurable-rules/json-schema-misconfigurations/)
4848
- [Azure APIM unsupported keywords](configurable-rules/azure-apim-unsupported-keyword/)
49+
- [Operation-deprecated-response-headers](configurable-rules/operation-deprecated-response-headers/)
4950

5051
### Custom plugins
5152

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
# `Deprecated` services SHOULD define a standard set of headers to communicate `Deprecation` and `Sunset` information. There should also exist a `Link` header to inform the consumer where the service location has been moved to, if any.
2+
3+
Authors:
4+
5+
- `@jeremyfiel` Jeremy Fiel (ADP)
6+
7+
## What this does and why
8+
9+
There are three parts to a deprecation strategy. Defining _when_ (`deprecation`) the service will be deprecated, the `sunset` date of the service for it to be completely turned off, and a `link` to where a replacement service may exist. We use a number of RFC standards to define these header fields.
10+
11+
- [RFC7231][4]
12+
- [RFC8288][1]
13+
- [RFC8594][3]
14+
- [RFC9651][5]
15+
- [Pending RFC][2]
16+
17+
### 2XX responses
18+
19+
_while the service remains active_
20+
21+
* We must define the requirement for the `headers` map to exist in a `2XX` response
22+
* We define the required headers: `deprecation`, `sunset`, `link`
23+
24+
### 410 Gone response
25+
26+
_the service is no longer available_
27+
28+
* A deprecated service must define a `410` response
29+
* We must define the requirement for the `headers` map to exist
30+
* After a service has been deprecated, the `deprecation` header must not be provided.
31+
* A `sunset` header to indicate when the service was removed and a `link` header to indicate where a new service can be found
32+
33+
## Code
34+
35+
Add this to the `rules` section of your `redocly.yaml`:
36+
37+
```yaml
38+
rules:
39+
rule/response-2XX-deprecated-must-define-headers:
40+
severity: warn
41+
message: Deprecated endpoints MUST respond with standard headers
42+
where:
43+
- subject:
44+
type: Operation
45+
property: deprecated
46+
assertions:
47+
defined: true
48+
const: true
49+
subject:
50+
type: Response
51+
matchParentKeys: '2([\d]+){2}'
52+
assertions:
53+
required:
54+
- headers
55+
56+
rule/response-2XX-deprecated-must-use-standard-headers:
57+
severity: warn
58+
message: 'Deprecated endpoints MUST respond with "Sunset", "Deprecation", and "Link" standard headers'
59+
where:
60+
- subject:
61+
type: Operation
62+
property: deprecated
63+
assertions:
64+
defined: true
65+
const: true
66+
- subject:
67+
type: Response
68+
matchParentKeys: '2([\d]+){2}'
69+
assertions:
70+
required:
71+
- headers
72+
subject:
73+
type: HeadersMap
74+
assertions:
75+
required:
76+
- Deprecation
77+
- Sunset
78+
- Link
79+
80+
rule/operation-deprecated-must-define-410-response:
81+
severity: warn
82+
message: Deprecated endpoints MUST define a 410 response
83+
where:
84+
- subject:
85+
type: Operation
86+
property: deprecated
87+
assertions:
88+
defined: true
89+
const: true
90+
subject:
91+
type: Responses
92+
assertions:
93+
required:
94+
- '410'
95+
96+
rule/response-410-deprecated-must-define-headers:
97+
severity: warn
98+
message: Deprecated endpoints MUST respond with standard headers
99+
where:
100+
- subject:
101+
type: Operation
102+
property: deprecated
103+
assertions:
104+
defined: true
105+
const: true
106+
subject:
107+
type: Response
108+
matchParentKeys: '410'
109+
assertions:
110+
required:
111+
- headers
112+
113+
rule/response-410-deprecated-must-define-standard-headers:
114+
severity: warn
115+
message: 'Deprecated endpoints MUST respond with "Sunset" and "Link" standard headers after "Deprecation" date value has been exceeded'
116+
where:
117+
- subject:
118+
type: Operation
119+
property: deprecated
120+
assertions:
121+
defined: true
122+
const: true
123+
- subject:
124+
type: Response
125+
matchParentKeys: '410'
126+
assertions:
127+
required:
128+
- headers
129+
subject:
130+
type: HeadersMap
131+
assertions:
132+
required:
133+
- 'Sunset'
134+
- 'Link'
135+
136+
rule/response-410-deprecated-must-not-define-deprecation-header:
137+
severity: warn
138+
message: 'Deprecated endpoints 410 response MUST NOT define "Deprecation" header'
139+
where:
140+
- subject:
141+
type: Operation
142+
property: deprecated
143+
assertions:
144+
defined: true
145+
const: true
146+
- subject:
147+
type: Response
148+
matchParentKeys: '410'
149+
assertions:
150+
required:
151+
- headers
152+
subject:
153+
type: HeadersMap
154+
assertions:
155+
disallowed:
156+
- 'Deprecation'
157+
```
158+
159+
## Examples
160+
161+
```yaml
162+
#invalid
163+
openapi: 3.1.0
164+
info:
165+
title: Redocly Configurable Rule - Deprecated Endpoints
166+
version: 0.0.0
167+
paths:
168+
'/things':
169+
summary: my deprecated endpoint
170+
deprecated: true
171+
responses:
172+
'200':
173+
description: OK
174+
content:
175+
'application/json':
176+
schema: {}
177+
```
178+
179+
```yaml
180+
# valid
181+
openapi: 3.1.0
182+
info:
183+
title: Redocly Configurable Rule - Deprecated Endpoints
184+
version: 0.0.0
185+
paths:
186+
'/things':
187+
summary: my deprecated endpoint
188+
deprecated: true
189+
parameters: []
190+
responses:
191+
'200':
192+
description: OK
193+
headers:
194+
deprecation:
195+
schema:
196+
type: string
197+
examples:
198+
deprecation_date:
199+
summary: A Structured Field Value as defined in Section 3.3.7 of RFC9651[5].
200+
value: '@1688169599'
201+
sunset:
202+
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
203+
schema:
204+
type: string
205+
examples:
206+
sunset_date:
207+
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231][4], and SHOULD be a timestamp in the future.
208+
value: Sun, 30 Jun 2024 23:59:59 GMT
209+
link:
210+
schema:
211+
type: string
212+
examples:
213+
link_value:
214+
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
215+
content:
216+
'application/json':
217+
schema: {}
218+
'410':
219+
description: Gone
220+
headers:
221+
sunset:
222+
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
223+
schema:
224+
type: string
225+
examples:
226+
sunset_date:
227+
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231][4], and SHOULD be a timestamp in the future.
228+
value: Sun, 30 Jun 2024 23:59:59 GMT
229+
link:
230+
schema:
231+
type: string
232+
examples:
233+
link_value:
234+
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
235+
content:
236+
'application/json':
237+
schema: {}
238+
```
239+
240+
[1]: https://datatracker.ietf.org/doc/html/rfc8288 "RFC8288 - Web Linking"
241+
[2]: https://datatracker.ietf.org/doc/draft-ietf-httpapi-deprecation-header/ "RFC pending publication - HTTP Deprecation Header Field"
242+
[3]: https://datatracker.ietf.org/doc/html/rfc8594/ "RFC8594 - HTTP Sunset Header Field"
243+
[4]: https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.1 "RFC7231 - Date/Time Formats"
244+
[5]: https://datatracker.ietf.org/doc/html/rfc9651/#section-3.3.7 "RFC9651 - Dates"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
openapi: 3.1.0
2+
info:
3+
title: Redocly Configurable Rule - Deprecated Endpoints
4+
version: 0.0.0
5+
paths:
6+
'/things':
7+
summary: my deprecated endpoint
8+
deprecated: true
9+
parameters: []
10+
responses:
11+
'200':
12+
description: OK
13+
headers:
14+
deprecation:
15+
schema:
16+
type: string
17+
examples:
18+
deprecation_date:
19+
summary: an Item Structured Header RFC8941. Refer to Section 3.3.7 of [SFBIS] for ABNF of `sf-date`
20+
value: '@1688169599'
21+
sunset:
22+
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
23+
schema:
24+
type: string
25+
examples:
26+
sunset_date:
27+
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231], and SHOULD be a timestamp in the future.
28+
value: Sun, 30 Jun 2024 23:59:59 GMT
29+
link:
30+
schema:
31+
type: string
32+
examples:
33+
link_value:
34+
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
35+
content:
36+
'application/json':
37+
schema: {}
38+
'410':
39+
description: Gone
40+
headers:
41+
sunset:
42+
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
43+
schema:
44+
type: string
45+
examples:
46+
sunset_date:
47+
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231], and SHOULD be a timestamp in the future.
48+
value: Sun, 30 Jun 2024 23:59:59 GMT
49+
link:
50+
schema:
51+
type: string
52+
examples:
53+
link_value:
54+
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
55+
content:
56+
'application/json':
57+
schema: {}

0 commit comments

Comments
 (0)