Skip to content

Specifying headers option in @output decorator generates invalid spec for OAS version >= 3.0.0 #631

@tsokalski

Description

@tsokalski

The OpenAPI Specification for versions 3.0.0 and higher indicates that the Header object must not specify either a name or an in field:

The current implementation introduced in #511 invokes schema2parameters from apispec, which leaves the fields in place, resulting in an invalid spec.

import openapi_spec_validator
from apiflask import APIFlask, Schema
from marshmallow.fields import String


class Foo(Schema):
    name = String()


class ResponseHeader(Schema):
    x_token = String(data_key="X-Token", metadata={"description": "A custom token header"})


app = APIFlask(__name__)


@app.route("/foo")
@app.output(Foo, headers=ResponseHeader)
def foo():
    pass


client = app.test_client()
rv = client.get("/openapi.json")
assert rv.status_code == 200
openapi_spec_validator.validate(rv.json)  # Fails

The generated spec looks like this:

{
    "components": {
        "schemas": {
            "Foo": {
                "properties": {
                    "name": {
                        "type": "string"
                    }
                },
                "type": "object"
            }
        }
    },
    "info": {
        "title": "APIFlask",
        "version": "0.1.0"
    },
    "openapi": "3.0.3",
    "paths": {
        "/foo": {
            "get": {
                "parameters": [],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Foo"
                                }
                            }
                        },
                        "description": "Successful response",
                        "headers": {
                            "X-Token": {
                                "description": "A custom token header",
                                "in": "header",
                                "name": "X-Token",
                                "required": false,
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "summary": "Foo"
            }
        }
    },
    "servers": [
        {
            "url": "http://localhost/"
        }
    ],
    "tags": []
}

I considered raising this against apispec, since in theory it might be possible to modify schema2parameters to not include name or in when the location value is headers, but the name value is still needed to populate the key of the headers dictionary in the spec, so I think it makes more sense to address in this project.

Environment:

  • Python version: 3.11
  • Flask version: 3.1.0
  • APIFlask version: 2.3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions