diff --git a/openapi_core/schema/schemas/models.py b/openapi_core/schema/schemas/models.py index cea36d7..6ae4dc9 100644 --- a/openapi_core/schema/schemas/models.py +++ b/openapi_core/schema/schemas/models.py @@ -2,13 +2,14 @@ import attr import functools import logging +from base64 import b64decode, b64encode from collections import defaultdict from datetime import date, datetime +from uuid import UUID import re import warnings from six import iteritems, integer_types, binary_type, text_type -from uuid import UUID from openapi_core.extensions.models.factories import ModelFactory from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType @@ -44,10 +45,12 @@ class Schema(object): STRING_FORMAT_CALLABLE_GETTER = { SchemaFormat.NONE: Format(text_type, TypeValidator(text_type)), - SchemaFormat.DATE: Format(format_date, TypeValidator(date, exclude=datetime)), + SchemaFormat.DATE: Format( + format_date, TypeValidator(date, exclude=datetime)), SchemaFormat.DATETIME: Format(format_datetime, TypeValidator(datetime)), SchemaFormat.BINARY: Format(binary_type, TypeValidator(binary_type)), SchemaFormat.UUID: Format(UUID, TypeValidator(UUID)), + SchemaFormat.BYTE: Format(b64decode, TypeValidator(binary_type)), } TYPE_VALIDATOR_CALLABLE_GETTER = { diff --git a/tests/integration/data/v3.0/petstore.yaml b/tests/integration/data/v3.0/petstore.yaml index 733c587..3f132c3 100644 --- a/tests/integration/data/v3.0/petstore.yaml +++ b/tests/integration/data/v3.0/petstore.yaml @@ -78,8 +78,8 @@ paths: - name: api_key in: header schema: - type: integer - format: int32 + type: string + format: byte required: true - name: user in: cookie diff --git a/tests/integration/test_petstore.py b/tests/integration/test_petstore.py index f1068c1..e1a3c8e 100644 --- a/tests/integration/test_petstore.py +++ b/tests/integration/test_petstore.py @@ -1,5 +1,6 @@ import json import pytest +from base64 import b64encode from uuid import UUID from six import iteritems @@ -30,6 +31,12 @@ from openapi_core.wrappers.mock import MockRequest, MockResponse class TestPetstore(object): + api_key = b'12345' + + @property + def api_key_encoded(self): + return b64encode(self.api_key) + @pytest.fixture def spec_dict(self, factory): return factory.spec_from_file("data/v3.0/petstore.yaml") @@ -424,7 +431,7 @@ class TestPetstore(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -440,7 +447,7 @@ class TestPetstore(object): assert parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -484,7 +491,7 @@ class TestPetstore(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -500,7 +507,7 @@ class TestPetstore(object): assert parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -544,7 +551,7 @@ class TestPetstore(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -560,7 +567,7 @@ class TestPetstore(object): assert parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -592,7 +599,7 @@ class TestPetstore(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -608,7 +615,7 @@ class TestPetstore(object): assert parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -631,7 +638,7 @@ class TestPetstore(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -647,7 +654,7 @@ class TestPetstore(object): assert parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -672,7 +679,7 @@ class TestPetstore(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -688,7 +695,7 @@ class TestPetstore(object): assert parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -711,7 +718,7 @@ class TestPetstore(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } request = MockRequest( diff --git a/tests/integration/test_validators.py b/tests/integration/test_validators.py index 55a1199..bfdd4f9 100644 --- a/tests/integration/test_validators.py +++ b/tests/integration/test_validators.py @@ -1,3 +1,4 @@ +from base64 import b64encode import json import pytest @@ -22,6 +23,12 @@ class TestRequestValidator(object): host_url = 'http://petstore.swagger.io' + api_key = b'12345' + + @property + def api_key_encoded(self): + return b64encode(self.api_key) + @pytest.fixture def spec_dict(self, factory): return factory.spec_from_file("data/v3.0/petstore.yaml") @@ -88,7 +95,7 @@ class TestRequestValidator(object): def test_missing_body(self, validator): headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -106,7 +113,7 @@ class TestRequestValidator(object): assert result.body is None assert result.parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -115,7 +122,7 @@ class TestRequestValidator(object): def test_invalid_content_type(self, validator): headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -133,7 +140,7 @@ class TestRequestValidator(object): assert result.body is None assert result.parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, @@ -159,7 +166,7 @@ class TestRequestValidator(object): } data = json.dumps(data_json) headers = { - 'api_key': '12345', + 'api_key': self.api_key_encoded, } cookies = { 'user': '123', @@ -175,7 +182,7 @@ class TestRequestValidator(object): assert result.errors == [] assert result.parameters == { 'header': { - 'api_key': 12345, + 'api_key': self.api_key, }, 'cookie': { 'user': 123, diff --git a/tests/unit/schema/test_schemas.py b/tests/unit/schema/test_schemas.py index 47f4011..302719f 100644 --- a/tests/unit/schema/test_schemas.py +++ b/tests/unit/schema/test_schemas.py @@ -478,6 +478,25 @@ class TestSchemaValidate(object): assert result == value + @pytest.mark.parametrize('value', [ + u('tsssst'), u('dGVzdA=='), + ]) + def test_string_format_byte_invalid(self, value): + schema = Schema('string', schema_format='byte') + + with pytest.raises(OpenAPISchemaError): + schema.validate(value) + + @pytest.mark.parametrize('value', [ + b('tsssst'), b('dGVzdA=='), + ]) + def test_string_format_byte(self, value): + schema = Schema('string', schema_format='byte') + + result = schema.validate(value) + + assert result == value + @pytest.mark.parametrize('value', [ u('test'), b('stream'), datetime.date(1989, 1, 2), datetime.datetime(1989, 1, 2, 0, 0, 0),