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

Multiple specifications for the header with the same name in components #1572

Open
slavafomin opened this issue May 6, 2018 · 15 comments
Open
Labels
headers param serialization Issues related to parameter and/or header serialization

Comments

@slavafomin
Copy link

slavafomin commented May 6, 2018

Hello!

According to the specification header object (in components section) must not include a name, the name is derived from the headers map's key instead.

But, what if I want to have multiple header specifications for the header with the same name?

For example, I can have different API endpoints (or groups of endpoints) which require different authentication parameters:

openapi: 3.0.1

info:
  version: 0.0.0
  title: Some Title
  description: Some description

paths:
  /foo/:
    post:
      parameters:
        - name: Authorization
          in: header
          schema:
            type: string
            minLength: 32
            maxLength: 64
            
      responses:
        200:
          description: Some description
          
  /bar/:
    post:
      parameters:
        - name: Authorization
          in: header
          required: true
          schema:
            type: string
            minLength: 128
            maxLength: 128
            
      responses:
        200:
          description: Some description

How do I extract those headers to components section and reference them with $ref?

I can do it this way, and actually swagger UI understand that and renders correctly:

openapi: 3.0.1

info:
  version: 0.0.0
  title: Some Title
  description: Some description

paths:
  /foo/:
    post:
      parameters:
        - $ref: '#/components/headers/auth1'
            
      responses:
        200:
          description: Some description
          
  /bar/:
    post:
      parameters:
        - $ref: '#/components/headers/auth2'
            
      responses:
        200:
          description: Some description

components:
  headers:
    auth1:
      name: Authorization
      schema:
        type: string
        minLength: 32
        maxLength: 64
    auth2:
      name: Authorization
      required: true
      schema:
        type: string
        minLength: 128
        maxLength: 128

But, it throws validation errors, because I'm using name property for headers specified in the components/headers section.

Also, if name is not referenced in the header specification, the Swagger UI doesn't display header's name at all (look like it doesn't know how to derive it from the headers map's key), but it's another issue with the Swagger itself, but it could also be a sign of a more major problem.

Could someone elaborate on this? Thank you!

@slavafomin slavafomin changed the title Multiple headers specification for the header with the same name in components Multiple specifications for the header with the same name in components May 6, 2018
@darrelmiller
Copy link
Member

It is not recommended to define HTTP Authorization headers in operations. That's what security requirement objects are designed to. The spec says tooling should ignore headers called Authorization.

Having the same HTTP header name with two different set of rules seems like an unwise thing to do. It certainly isn't how standard HTTP headers are defined.

@dfornika
Copy link

I'm interested in this issue for the purpose of using the Link header for web linking. There's an example in the RFC that shows multiple links being serialized either in a single Link header or multiple headers. It seems like it would be simpler to parse the links if they were in separate headers.

@handrews
Copy link
Member

@hibaymj didn't you have some idea on how to handle multiple Link headers in OAS?

@darrelmiller
Copy link
Member

@dfornika Parsing a single link header is hard. Parsing two is really not that much harder. I just borrowed someone elses code when I needed to do it :-) https://github.com/tavis-software/Tavis.Link/blob/a6877ff4a98e3de662d52b281e06661957437ed5/src/Link/LinkHeaders/LinkHeaderParser.cs

@handrews
Copy link
Member

@darrelmiller the problem comes when trying to specify what links will or may be present. If you are making heavy use of the Link header as your hypermedia strategy, you need to be able to indicate what rel values are present in responses, preferably without imposing an order on them. If one is forced to treat the value as a single string (comma-separated for multiple link values since the object format makes it impossible to specify each value separately), then you are in trouble. Regular expressions are not expressive for such cases.

@dfornika
Copy link

Yes @handrews that's exactly the situation I have in mind. I'm not sure if this is helpful but I made a couple of regex demos to demonstrate how it may be feasible to write regexes for relatively simple cases where each link is in a separate header, but it would be very difficult to do for multiple links in a single header.

Single Link header with multiple links
Multiple Link headers, each with one link

@handrews
Copy link
Member

@dfornika right- and even that Single Link header with multiple links regex imposes an ordering on the links, which is not good as now it will break if the server reorders them for whatever reason.

@hibaymj
Copy link

hibaymj commented Mar 27, 2019

@handrews I concur that regex is not really up to the task of parsing multiple link headers with any associated semantics. Like @darrelmiller showed, I think it's really a case where some custom parsing is required.

The thinking I had for multiple Links to be returned within a current OAS document was to define a schema which would describe the network and system semantics of the potential response, the ordering, the range of rel values, if a rel is required, while leaving domain semantics out of scope. This schema would then use the alternate schema functionality in #1532.

@darrelmiller wrote:

Having the same HTTP header name with two different set of rules seems like an unwise thing to do. It certainly isn't how standard HTTP headers are defined.

I think this is related to the fact that there are some headers which are defined with strict bounds, and others like Link or Prefer which have some characteristics of a collector or container. I make the suggestion above, because to include multiple versions of a header in the same scope would likely present a difficult challenge for the tooling ecosystem and would require time to work through. While, alternate schema would at least provide a sufficient stopgap until the root spec could evolve.

@handrews handrews added the param serialization Issues related to parameter and/or header serialization label Jan 28, 2024
@rafalkrupinski
Copy link

Disregarding Link or any other particular header, it seems it's a limitation of OpenAPI 3.0 that #/components/headers can have each header only once.

The limitation only appears when two or more operations have headers with the same name but with other properties different. Not the best API design, nonetheless possible.

@handrews
Copy link
Member

handrews commented Jun 5, 2024

@rafalkrupinski I'm not sure I follow. The name of a component in the Components Object is not related to the HTTP header name. EDIT: see next comment

@handrews
Copy link
Member

handrews commented Jun 5, 2024

@rafalkrupinski oh wow I've read this issue wrong... I assumed it was about objects of Header Objects not allowing duplicates (which is true because the header name is the object key).

But the OP specifically mentioned the Components Object.

I think the error here is due to two things:

@rafalkrupinski
Copy link

#/components/headers is an object of header objects and they forbid name property, so the headers there must use their keys for names too, don't they?

@handrews
Copy link
Member

handrews commented Jun 6, 2024

@rafalkrupinski #/componets/headers/Foo doesn't do anything unless it's referenced. So it's the name where the reference exists that matters.

In this example, the header name is X-ActualHeader. The name NotAHeaderName is irrelevant except for its use in the JSON Pointer in the $ref. But it has nothing to do with the header being used. I imagine people often name the component after the header, but therer's no reason you need to. So you could have two different definitions for X-ActualHeader in your Components Object as long as you name the two components something different.

components:
  headers:
    NotAHeaderName:
      schema: {...}
paths:
  /whatever:
    get:
      responses:
        "200":
          headers:
            X-ActualHeader:
              $ref: "#/components/headers/NotAHeaderName"

@handrews
Copy link
Member

handrews commented Jun 6, 2024

And yes, it's weird to separate the name from the description - that's one reason that we've talked about using arrays more than objects in Moonwalk (OAS 4).

@rafalkrupinski
Copy link

rafalkrupinski commented Jun 6, 2024

So it's the name where the reference exists that matters.

🤦 Of course

I think this should answer OP's problem, at least if we disregard the fact that they were trying to reference headers from parameters edit: and that it's about authorization headers.

that's one reason that we've talked about using arrays more than objects in Moonwalk (OAS 4).

But I suppose children of components will remain objects either way, otherwise you'd need to reference them by index... or by their name property instead of ref.
I think the better solution are the proposed header groups, then you could reference groups by their paths, and headers could keep keys for names:

components:
  header-groups:
    rate-limited: # arbitrary name
      x-rate-limit: # real header name
        schema: ...
      x-reset:
        schema: ...
paths:
  /op:
    get:
      responses:
        "200":
          headers-groups:
          - $ref: '#/components/header-groups/rate-limited'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
headers param serialization Issues related to parameter and/or header serialization
Projects
None yet
Development

No branches or pull requests

6 participants