Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add w3c support to 233a #55

Merged
merged 1 commit into from
May 27, 2024
Merged
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ npm run lint-fix # format source files
| [#229][#229] | [SHOULD consider to design `POST` and `PATCH` idempotent][#229] | :grey_exclamation: | :grey_exclamation: | - |
| [#230][#230] | [MAY consider to support `Idempotency-Key` header][#230] | :grey_exclamation: | :grey_exclamation: | - |
| [#231][#231] | [Should use secondary key for idempotent `POST` design][#231] | :grey_exclamation: | :grey_exclamation: | - |
| [#233a][#233a] | [MUST request must use b3 tracing headers][#233a] | - | :heavy_check_mark: | - |
| [#233a][#233a] | [MUST request must use tracing headers][#233a] | - | :heavy_check_mark: | - |
| [#234][#234] | [MUST only use durable and immutable remote references][#234] | :grey_exclamation: | :grey_exclamation: | - |
| [#235][#235] | [SHOULD name date/time properties with `_at` suffix][#235] | - | - | - |
| [#236][#236] | [SHOULD design simple query languages using query parameters][#236] | :grey_exclamation: | :grey_exclamation: | - |
Expand Down Expand Up @@ -368,7 +368,7 @@ npm run lint-fix # format source files
[#230]: https://opensource.zalando.com/restful-api-guidelines/#230
[#231]: https://opensource.zalando.com/restful-api-guidelines/#231
[#233]: https://opensource.zalando.com/restful-api-guidelines/#233
[#233a]: ./doc/rules/requests-must-use-b3-tracing.md
[#233a]: ./doc/rules/requests-must-use-tracing.md
[#234]: https://opensource.zalando.com/restful-api-guidelines/#234
[#235]: https://opensource.zalando.com/restful-api-guidelines/#235
[#236]: https://opensource.zalando.com/restful-api-guidelines/#236
Expand Down
18 changes: 9 additions & 9 deletions baloise.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extends: [./zalando.yml] # We're extending the zalando ruleset by replacing or adding baloise specific rules.

functions:
- validate-b3-tracing
- validate-tracing
- assert-http-codes-for-operation

rules:
Expand Down Expand Up @@ -149,21 +149,21 @@ rules:
'default': [ ALL ]


# MUST request must provide b3 tracing [233a]
# MUST request must provide tracing [233a]
# => Alternative to https://opensource.zalando.com/restful-api-guidelines/#233

must-use-b3-tracing:
message: B3 header X-B3-Traceid or X-B3-Spanid missing
description: MUST use b3 tracing [233a]
documentationUrl: https://github.com/baloise-incubator/spectral-ruleset/blob/main/doc/rules/requests-must-use-b3-tracing.md
must-use-tracing:
message: Header X-B3-Traceid, X-B3-Spanid or traceparent (w3c) missing
description: MUST use b3 or w3c tracing [233a]
documentationUrl: https://github.com/baloise-incubator/spectral-ruleset/blob/main/doc/rules/requests-must-use-tracing.md
severity: error
given: $.paths.*
then:
function: validate-b3-tracing
function: validate-tracing


# MUST provide API audience [219]
# => https://opensource.zalando.com/restful-api-guidelines/#219
# MUST provide API audience [219]
# => https://opensource.zalando.com/restful-api-guidelines/#219

must-provide-api-audience: off

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# MUST request must provide b3 tracing headers
# MUST request must provide tracing headers
The following header parameter must be provided for any request:

- `X-B3-Traceid`
- `X-B3-Spanid`
or
- `traceparent`

Specification: You can find the specification for b3 [here](https://github.com/openzipkin/b3-propagation)
Specification: You can find the specification for b3 [here](https://github.com/openzipkin/b3-propagation) and w3c [here](https://www.w3.org/TR/trace-context/)
Rationale: We have an internal survey with all developers and the decision was b3 [Internal link](https://confluence.baloisenet.com/atlassian/x/LxWJj).
20 changes: 17 additions & 3 deletions functions/validate-b3-tracing.js → functions/validate-tracing.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,22 @@ function isB3Valid(targetValue) {
return !(b3Params.length !== 2 || !b3Params.every((param) => param.in === 'header'));
}

function isW3cValid(targetValue) {
if (!Array.isArray(targetValue)) {
return [
{
message: `No array given, provide $.paths.*.*.parameters`,
},
];
}

const w3cParams = targetValue.filter((param) => param.name && param.name.toLowerCase() === 'traceparent');

return !(w3cParams.length !== 1 || !w3cParams.every((param) => param.in === 'header'));
}

export default (targetValue) => {
if (targetValue.parameters && isB3Valid(targetValue.parameters)) {
if (targetValue.parameters && (isB3Valid(targetValue.parameters) || isW3cValid(targetValue.parameters))) {
return [];
}

Expand All @@ -27,12 +41,12 @@ export default (targetValue) => {
['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'].includes(verb.toLowerCase()),
)
.map((verb) => targetValue[verb])
.some((operation) => operation.parameters && !isB3Valid(operation.parameters));
.some((operation) => operation.parameters && !isB3Valid(operation.parameters) && !isW3cValid(operation.parameters));

if (hasInvalidEntry) {
return [
{
message: `B3 header X-B3-Traceid or X-B3-Spanid missing`,
message: `Header X-B3-Traceid, X-B3-Spanid or traceparent (w3c) missing`,
},
];
}
Expand Down
34 changes: 30 additions & 4 deletions tests/233a-MUST-request-must-provide-b3-tracing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ describe('MUST request must provide b3 tracing [233a]', () => {
const result = await lint(openApi, 'baloise');
expect(result).toEqual([
expect.objectContaining({
code: 'must-use-b3-tracing',
message: 'B3 header X-B3-Traceid or X-B3-Spanid missing',
code: 'must-use-tracing',
message: 'Header X-B3-Traceid, X-B3-Spanid or traceparent (w3c) missing',
severity: DiagnosticSeverity.Error,
}),
]);
Expand All @@ -27,8 +27,8 @@ describe('MUST request must provide b3 tracing [233a]', () => {
const result = await lint(openApi, 'baloise');
expect(result).toEqual([
expect.objectContaining({
code: 'must-use-b3-tracing',
message: 'B3 header X-B3-Traceid or X-B3-Spanid missing',
code: 'must-use-tracing',
message: 'Header X-B3-Traceid, X-B3-Spanid or traceparent (w3c) missing',
severity: DiagnosticSeverity.Error,
}),
]);
Expand Down Expand Up @@ -59,4 +59,30 @@ describe('MUST request must provide b3 tracing [233a]', () => {
const result = await lint(openApi, 'baloise');
expect(result).toEqual([]);
});

test('Assert w3c tracing headers valid', async () => {
const openApi = await loadOpenApiSpec('base-openapi.yml');
openApi.paths['/example'].get.parameters = openApi.paths['/example'].get.parameters.filter(
(param: { $ref: string }) =>
!param['$ref'] &&
param['$ref'] !== '#/components/parameters/HeaderB3TraceId' &&
param['$ref'] !== '#/components/parameters/HeaderB3SpanId',
);
openApi.paths['/example'].get.parameters.push({
$ref: '#/components/parameters/HeaderW3cTraceparent',
});

const result = await lint(openApi, 'baloise');
expect(result).toEqual([]);
});

test('Assert w3c and b3 tracing headers valid', async () => {
const openApi = await loadOpenApiSpec('base-openapi.yml');
openApi.paths['/example'].get.parameters.push({
$ref: '#/components/parameters/HeaderW3cTraceparent',
});

const result = await lint(openApi, 'baloise');
expect(result).toEqual([]);
});
});
6 changes: 6 additions & 0 deletions tests/fixtures/base-openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ components:
required: false
schema:
type: string
HeaderW3cTraceparent:
in: header
name: traceparent
required: true
schema:
type: string
schemas:
Example:
type: object
Expand Down
Loading