Skip to content

[Bug]: Does Not Support Binary Response Types #245

@its-hammer-time

Description

@its-hammer-time

Actual Behavior

I hacked together the code below so that I could test this library in isolation, but for context we are using it inside of a Pyramid app. When I run the case below, I get the following exception:

openapi_core.validation.response.exceptions.InvalidData: InvalidData: Value b'<pdf_content>' not valid for schema of type string: (<ValidationError: "b'<pdf_content>' is not of type 'string'">,)

If I then try to wrap it inside of a str(), I get is not of type 'binary' so I believe there is an issue with the formatter understanding the bytes as a string.

Expected Behavior

If I return a binary object (pdf file) it should pass validation.

Steps to Reproduce

import typing as t

from openapi_core import OpenAPI
from openapi_core.validation.request.datatypes import RequestParameters


class OpenAPIRequest:
    def __init__(self) -> None:
        self.parameters = RequestParameters(
            path={},
            query={},
            header={},
            cookie={},
        )

    @property
    def host_url(self) -> str:
        return "https://example.com"

    @property
    def path(self) -> str:
        return "/test"

    @property
    def path_pattern(self) -> str:
        return "/test"

    @property
    def method(self) -> str:
        return "get"

    @property
    def body(self) -> t.Optional[t.Union[bytes, str, t.Dict]]:
        return None

    @property
    def content_type(self) -> str:
        return ""

    @property
    def mimetype(self) -> str:
        return ""


class OpenAPIResponse:
    def __init__(self, data: any) -> None:
        self._data = data

    @property
    def data(self) -> t.Optional[bytes]:
        return self._data

    @property
    def status_code(self) -> int:
        return 200

    @property
    def content_type(self) -> str:
        return "application/pdf"

    @property
    def mimetype(self) -> str:
        return "application/pdf"

    @property
    def headers(self) -> t.Mapping[str, t.Any]:
        return {
            "Content-Type": "application/pdf",
            "Content-Disposition": "attachment; filename=invoice.pdf",
        }


if __name__ == "__main__":
    with open('example-pdf.pdf', 'rb') as f:
        pdf_content = f.read()

    open_api_spec = OpenAPI.from_dict({
        "openapi": "3.1.0",
        "info": {
            "title": "Test spec",
            "version": "1.0.0",
            "description": "Test spec",
        },
        "servers": [
            {"url": "https://example.com"},
        ],
        "paths": {
            "/test": {
                "get": {
                    "responses": {
                        "200": {
                            "description": "OK",
                            "content": {
                                "application/pdf": {
                                    "schema": {
                                        "type": "string",
                                        "format": "binary",
                                    },
                                },
                            },
                        },
                    },
                },
            }
        }
    })

    request = OpenAPIRequest()
    response = OpenAPIResponse(data=pdf_content)
    open_api_spec.validate_response(request=request, response=response)

OpenAPI Core Version

0.19.1

OpenAPI Core Integration

Natively using openapi-core

Affected Area(s)

Validation

References

No response

Anything else we need to know?

No response

Would you like to implement a fix?

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions