Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ There are some fantastic examples of [configurable rules](https://redocly.com/do
- [String schemas length defined](configurable-rules/string-schemas-length-defined/)
- [JSON Schema misconfigurations](configurable-rules/json-schema-misconfigurations/)
- [Azure APIM unsupported keywords](configurable-rules/azure-apim-unsupported-keyword/)
- [Operation-deprecated-response-headers](configurable-rules/operation-deprecated-response-headers/)

### Custom plugins

Expand Down
244 changes: 244 additions & 0 deletions configurable-rules/operation-deprecated-response-headers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
# `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

Authors:

- `@jeremyfiel` Jeremy Fiel (ADP)

## What this does and why

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.

- [RFC7231][4]
- [RFC8288][1]
- [RFC8594][3]
- [RFC9651][5]
- [RFC9745][2]

### 2XX responses

_while the service remains active_

* We must define the requirement for the `headers` map to exist in a `2XX` response
* We define the required headers: `deprecation`, `sunset`, `link`

### 410 Gone response

_the service is no longer available_

* A deprecated service must define a `410` response
* We must define the requirement for the `headers` map to exist
* After a service has been deprecated, the `deprecation` header must not be provided.
* A `sunset` header to indicate when the service was removed and a `link` header to indicate where a new service can be found

## Code

Add this to the `rules` section of your `redocly.yaml`:

```yaml
rules:
rule/response-2XX-deprecated-must-define-headers:
severity: warn
message: Deprecated endpoints MUST respond with standard headers
where:
- subject:
type: Operation
property: deprecated
assertions:
defined: true
const: true
subject:
type: Response
matchParentKeys: '2([\d]+){2}'
assertions:
required:
- headers

rule/response-2XX-deprecated-must-use-standard-headers:
severity: warn
message: 'Deprecated endpoints MUST respond with "Sunset", "Deprecation", and "Link" standard headers'
where:
- subject:
type: Operation
property: deprecated
assertions:
defined: true
const: true
- subject:
type: Response
matchParentKeys: '2([\d]+){2}'
assertions:
required:
- headers
subject:
type: HeadersMap
assertions:
required:
- Deprecation
- Sunset
- Link

rule/operation-deprecated-must-define-410-response:
severity: warn
message: Deprecated endpoints MUST define a 410 response
where:
- subject:
type: Operation
property: deprecated
assertions:
defined: true
const: true
subject:
type: Responses
assertions:
required:
- '410'

rule/response-410-deprecated-must-define-headers:
severity: warn
message: Deprecated endpoints MUST respond with standard headers
where:
- subject:
type: Operation
property: deprecated
assertions:
defined: true
const: true
subject:
type: Response
matchParentKeys: '410'
assertions:
required:
- headers

rule/response-410-deprecated-must-define-standard-headers:
severity: warn
message: 'Deprecated endpoints MUST respond with "Sunset" and "Link" standard headers after "Deprecation" date value has been exceeded'
where:
- subject:
type: Operation
property: deprecated
assertions:
defined: true
const: true
- subject:
type: Response
matchParentKeys: '410'
assertions:
required:
- headers
subject:
type: HeadersMap
assertions:
required:
- 'Sunset'
- 'Link'

rule/response-410-deprecated-must-not-define-deprecation-header:
severity: warn
message: 'Deprecated endpoints 410 response MUST NOT define "Deprecation" header'
where:
- subject:
type: Operation
property: deprecated
assertions:
defined: true
const: true
- subject:
type: Response
matchParentKeys: '410'
assertions:
required:
- headers
subject:
type: HeadersMap
assertions:
disallowed:
- 'Deprecation'
```

## Examples

```yaml
#invalid
openapi: 3.1.0
info:
title: Redocly Configurable Rule - Deprecated Endpoints
version: 0.0.0
paths:
'/things':
summary: my deprecated endpoint
deprecated: true
responses:
'200':
description: OK
content:
'application/json':
schema: {}
```

```yaml
# valid
openapi: 3.1.0
info:
title: Redocly Configurable Rule - Deprecated Endpoints
version: 0.0.0
paths:
'/things':
summary: my deprecated endpoint
deprecated: true
parameters: []
responses:
'200':
description: OK
headers:
deprecation:
schema:
type: string
examples:
deprecation_date:
summary: A Structured Field Value as defined in Section 3.3.7 of RFC9651[5].
value: '@1688169599'
sunset:
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
schema:
type: string
examples:
sunset_date:
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231][4], and SHOULD be a timestamp in the future.
value: Sun, 30 Jun 2024 23:59:59 GMT
link:
schema:
type: string
examples:
link_value:
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
content:
'application/json':
schema: {}
'410':
description: Gone
headers:
sunset:
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
schema:
type: string
examples:
sunset_date:
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231][4], and SHOULD be a timestamp in the future.
value: Sun, 30 Jun 2024 23:59:59 GMT
link:
schema:
type: string
examples:
link_value:
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
content:
'application/json':
schema: {}
```

[1]: https://datatracker.ietf.org/doc/html/rfc8288 "RFC8288 - Web Linking"
[2]: https://datatracker.ietf.org/doc/html/rfc9745/ "RFC 9745 - HTTP Deprecation Header Field"
[3]: https://datatracker.ietf.org/doc/html/rfc8594/ "RFC8594 - HTTP Sunset Header Field"
[4]: https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.1 "RFC7231 - Date/Time Formats"
[5]: https://datatracker.ietf.org/doc/html/rfc9651/#section-3.3.7 "RFC9651 - Dates"
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
openapi: 3.1.0
info:
title: Redocly Configurable Rule - Deprecated Endpoints
version: 0.0.0
paths:
'/things':
summary: my deprecated endpoint
deprecated: true
parameters: []
responses:
'200':
description: OK
headers:
deprecation:
schema:
type: string
examples:
deprecation_date:
summary: an Item Structured Header RFC8941. Refer to Section 3.3.7 of [SFBIS] for ABNF of `sf-date`
value: '@1688169599'
sunset:
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
schema:
type: string
examples:
sunset_date:
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231], and SHOULD be a timestamp in the future.
value: Sun, 30 Jun 2024 23:59:59 GMT
link:
schema:
type: string
examples:
link_value:
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
content:
'application/json':
schema: {}
'410':
description: Gone
headers:
sunset:
description: Please note that for historical reasons the Sunset HTTP header field uses a different data type for date than the Deprecation header field
schema:
type: string
examples:
sunset_date:
summary: An HTTP-date timestamp, as defined in Section 7.1.1.1 of [RFC7231], and SHOULD be a timestamp in the future.
value: Sun, 30 Jun 2024 23:59:59 GMT
link:
schema:
type: string
examples:
link_value:
value: <https://example.org/more-things/123>; rel=alternate; title='the more-things api'
content:
'application/json':
schema: {}
Loading
Loading