Bug: header fields `name` and `in` not expected here - Parameter Object
jeremyfiel opened this issue · comments
What happened?
I have a large set of headers defined as components
. It seems only some of the headers will produce an error for not expected here
.
My JSON schema is valid and consistent with all other headers using a similar schema.
Minimal reproducible OpenAPI snippet
{
"components": {
"parameters": {
"header_Content-Language": {
"name": "Content-Language",
"in": "header",
"description": "Specifies the languages for which the entity-body is intended ",
"required": false,
"schema": {
"type": "string"
}
},
"header_Location": {
"name": "Location",
"in": "header",
"description": "Used to redirect the recipient to a location other the request URI for completion of the request or identification of a new resource",
"required": false,
"schema": {
"$ref": "../../../common/uriType_v01.json"
}
}
}
}
}
Screenshots
Example of the error produced
Example of a valid component schema
Additional Content
Version: 1.65.2 (user setup)
Commit: c722ca6c7eed3d7987c0d5c3df5c45f6b15e77d1
Date: 2022-03-10T14:33:55.248Z
Electron: 13.5.2
Chromium: 91.0.4472.164
Node.js: 14.16.0
V8: 9.1.269.39-electron.0
OS: Windows_NT x64 10.0.19042
Does this show problems if you run openapi lint
too?
yes. using beta89 I have the following output
[5] filename-swagger_v1.json:543:5 at #/components/parameters/header_Cache-Control/name
Property name
is not expected here.
541 | "header_Cache-Control": {
542 | "description": "Specifies directives that must be obeyed by all caching mechanisms along the request/response chain",
543 | "name": "Cache-Control",
544 | "in": "header",
545 | "schema": {
Error was generated by the spec rule.
[6] filename-swagger_v1.json:544:5 at #/components/parameters/header_Cache-Control/in
Property in
is not expected here.
542 | "description": "Specifies directives that must be obeyed by all caching mechanisms along the request/response chain",
543 | "name": "Cache-Control",
544 | "in": "header",
545 | "schema": {
546 | "type": "string"
Error was generated by the spec rule.
[7] filename-swagger_v1.json:535:5 at #/components/parameters/header_ETag/name
Property name
is not expected here.
533 | "header_ETag": {
534 | "description": "Defines the entity tag for use with the If-Match and If-None-Match request headers",
535 | "name": "ETag",
536 | "in": "header",
537 | "schema": {
Error was generated by the spec rule.
[8] filename-swagger_v1.json:536:5 at #/components/parameters/header_ETag/in
Property in
is not expected here.
534 | "description": "Defines the entity tag for use with the If-Match and If-None-Match request headers",
535 | "name": "ETag",
536 | "in": "header",
537 | "schema": {
538 | "type": "string"
Error was generated by the spec rule.
[9] filename-swagger_v1.json:516:5 at #/components/parameters/header_Last-Modified/name
Property name
is not expected here.
514 | },
515 | "header_Last-Modified": {
516 | "name": "Last-Modified",
517 | "in": "header",
518 | "description": "Specifies the date and time the representational state of the resource was last modified",
Error was generated by the spec rule.
[10] filename-swagger_v1.json:517:5 at #/components/parameters/header_Last-Modified/in
Property in
is not expected here.
515 | "header_Last-Modified": {
516 | "name": "Last-Modified",
517 | "in": "header",
518 | "description": "Specifies the date and time the representational state of the resource was last modified",
519 | "required": true,
Error was generated by the spec rule.
[11] filename-swagger_v1.json:525:5 at #/components/parameters/header_Content-Language/name
Property name
is not expected here.
523 | },
524 | "header_Content-Language": {
525 | "name": "Content-Language",
526 | "in": "header",
527 | "description": "Specifies the languages for which the entity-body is intended ",
Error was generated by the spec rule.
[12] filename-swagger_v1.json:526:5 at #/components/parameters/header_Content-Language/in
Property in
is not expected here.
524 | "header_Content-Language": {
525 | "name": "Content-Language",
526 | "in": "header",
527 | "description": "Specifies the languages for which the entity-body is intended ",
528 | "required": false,
Error was generated by the spec rule.
more context on this issue.
OAS 3.x.x supports a header
object and the schema does not allow name
and in
. Otherwise, the schema is semantically identical to the parameter
object. The header
object is expected in the headers
map defined in components
>headers
and is supposed to be used as Response headers throughout the definition. If I want to send request headers where a requestBody
doesn't exist, such as a GET
operation using caching headers ETag
, If-Match
etc.., OAS forces me to use parameters
rather than headers
components because the headers
map is only available in the encoding
object under content negotiation of a request body. A GET operation shouldn't have a request body but there are plenty of times I need to use headers in the request.
The bug I reported is mis-identifying parameter
objects with the in: header
identifier and flagging them as invalid.
{
"openapi": "3.0.3",
"servers": [
{
"url": "https://__host__/"
}
],
"info": {
"description": "Test api",
"version": "1.0.0",
"title": "empty title"
},
"paths": {
"/some-path/{aoid}": {
"get": {
"description": "some description",
"tags": [
"a tag"
],
"summary": "what it does",
"parameters": [
{
"$ref": "#/components/parameters/path_aoid"
},
{
"$ref": "#/components/parameters/query_filter"
},
{
"$ref": "#/components/parameters/header_If-Match"
}
],
"responses": {
"200": {
"description": "Ok",
"headers": {
"ETag": {
"$ref": "#/components/headers/ETag"
},
"Last-Modified": {
"$ref": "#/components/headers/Last-Modified"
}
},
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
},
"components": {
"parameters": {
"path_aoid": {
"name": "aoid",
"in": "path",
"description": "a param",
"required": true,
"schema": {
"$ref": "../../../common/associateOIDType_v01.json"
}
},
"header_If-Match": {
"name": "If-Match",
"in": "header",
"description": "If-Match caching policy",
"required": true,
"schema": {
"type": "string"
}
}
},
"headers": {
"ETag": {
"description": "Defines the entity tag for use with the If-Match and If-None-Match request headers",
"schema": {
"type": "string"
}
},
"Last-Modified": {
"name": "Last-Modified",
"in": "header",
"description": "Specifies the date and time the representational state of the resource was last modified",
"required": true,
"schema": {
"type": "string"
}
}
}
}
}
If a parameter
object is defined in components
>parameters
and uses in: header
as the identifier, it should be treated as a parameter
object, not a header
object.
You can see in the original screenshot where i have everything in parameters and some are having errors and some are not. The snippet was just explaining the issue. In my actual file I'm not using components>headers at all. Only components>parameters
In your original file do you reference components>parameters from the headers section?
i am referencing components>parameters from response object > headers map.
That's the problem.
Object->headers
expects header objects, not parameter objects so openapi-cli correctly reports the name
and in
fields are not expected there.
I understand your intent and that you do it on purpose but it may mean someone made a mistake and we don't have a way to distinguish.
You have to add some duplication to be spec compliant.
Moreover, this goes against OAS 3 spec. Official OAS 3 json-schema cannot catch this issue though due to json-schema limitations.
If you check the corresponding schema you will notice oneOf
that allows either header object or ref object. You have a ref there so the validation pass but json-schema can't validate the destination of $ref. You can check it by pointing $ref
to something completely unrelated, e.g. Response Object and your definition will still pass official JSON Schema validation.
If you check the definition of Header object it has additionalProperties: false
so it does not allow any other properties.
If you dereference your schema and run it against OAS 3 official JSON Schema it will show you that name
and in
fields are not expected there.
thanks @RomanHotsiy
I think you're right. I'm OOO but will definitely check that when I return. It makes more sense now why only some headers are showing name
and in
errors.. they are probably referenced in the Response>Headers
object.
@RomanHotsiy
I'm looking at this again and I'm having difficulty convincing myself and others that it's actually a problem.
Swagger, stoplight and redoc are all rendering these headers in the UI as expected, but the linting is failing. Changing all of our specs to clear this error is going to be a tough sell to our design team.
is this behavior correct or does it assume the header pointer and ignore the name/in props?
both have the same output on the UI.
The purpose of Redoc is not to enforce the spec. It is extremely lenient and you may make a lot of errors. Its goal is to render what it can as best as it can. The goal of the lint
command here is something else entirely. It's to enforce API design standards including specification compliance.
From the spec:
name
MUST NOT be specified, it is given in the corresponding headers map.in
MUST NOT be specified, it is implicitly in header.- All traits that are affected by the location MUST be applicable to a location of header (for example,
style
).
Source OAS 3.1: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#header-object
Source OAS 3.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#header-object