Skip to content

Commit 852c081

Browse files
committed
deserialize data form media type
1 parent 7a83f01 commit 852c081

File tree

3 files changed

+61
-5
lines changed

3 files changed

+61
-5
lines changed

openapi_core/deserializing/media_types/factories.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from openapi_core.deserializing.media_types.util import json_loads, form_loads
1+
from openapi_core.deserializing.media_types.util import (
2+
json_loads, urlencoded_form_loads, data_form_loads,
3+
)
24

35
from openapi_core.deserializing.media_types.deserializers import (
46
PrimitiveDeserializer,
@@ -9,7 +11,8 @@ class MediaTypeDeserializersFactory(object):
911

1012
MEDIA_TYPE_DESERIALIZERS = {
1113
'application/json': json_loads,
12-
'application/x-www-form-urlencoded': form_loads,
14+
'application/x-www-form-urlencoded': urlencoded_form_loads,
15+
'multipart/form-data': data_form_loads,
1316
}
1417

1518
def __init__(self, custom_deserializers=None):

openapi_core/deserializing/media_types/util.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from email.parser import BytesParser
12
from json import loads
23

34
from six import binary_type
@@ -11,5 +12,19 @@ def json_loads(value):
1112
return loads(value)
1213

1314

14-
def form_loads(value):
15+
def urlencoded_form_loads(value):
1516
return dict(parse_qsl(value))
17+
18+
19+
def data_form_loads(value):
20+
if issubclass(type(value), str):
21+
value = value.encode()
22+
parser = BytesParser()
23+
parts = parser.parsebytes(value)
24+
return dict(
25+
(
26+
part.get_param('name', header='content-disposition'),
27+
part.get_payload(decode=True),
28+
)
29+
for part in parts.get_payload()
30+
)

tests/unit/deserializing/test_media_types_deserializers.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from email.mime.multipart import MIMEMultipart
2+
from email.mime.nonmultipart import MIMENonMultipart
3+
14
import pytest
25

36
from openapi_core.deserializing.exceptions import DeserializeError
@@ -7,6 +10,24 @@
710
from openapi_core.schema.media_types.models import MediaType
811

912

13+
class MIMEFormdata(MIMENonMultipart):
14+
def __init__(self, keyname, *args, **kwargs):
15+
super(MIMEFormdata, self).__init__(*args, **kwargs)
16+
self.add_header(
17+
"Content-Disposition", "form-data; name=\"%s\"" % keyname)
18+
19+
20+
def encode_multipart_formdata(fields):
21+
m = MIMEMultipart("form-data")
22+
23+
for field, value in fields.items():
24+
data = MIMEFormdata(field, "text", "plain")
25+
data.set_payload(value)
26+
m.attach(data)
27+
28+
return m
29+
30+
1031
class TestMediaTypeDeserializer(object):
1132

1233
@pytest.fixture
@@ -31,22 +52,39 @@ def test_json_empty_object(self, deserializer_factory):
3152

3253
assert result == {}
3354

34-
def test_form_urlencoded_empty(self, deserializer_factory):
55+
def test_urlencoded_form_empty(self, deserializer_factory):
3556
media_type = MediaType('application/x-www-form-urlencoded')
3657
value = ''
3758

3859
result = deserializer_factory(media_type)(value)
3960

4061
assert result == {}
4162

42-
def test_form_urlencoded_simple(self, deserializer_factory):
63+
def test_urlencoded_form_simple(self, deserializer_factory):
4364
media_type = MediaType('application/x-www-form-urlencoded')
4465
value = 'param1=test'
4566

4667
result = deserializer_factory(media_type)(value)
4768

4869
assert result == {'param1': 'test'}
4970

71+
@pytest.mark.parametrize('value', [b'', ''])
72+
def test_data_form_empty(self, deserializer_factory, value):
73+
media_type = MediaType('multipart/form-data')
74+
75+
result = deserializer_factory(media_type)(value)
76+
77+
assert result == {}
78+
79+
def test_data_form_simple(self, deserializer_factory):
80+
media_type = MediaType('multipart/form-data')
81+
formdata = encode_multipart_formdata({'param1': 'test'})
82+
value = str(formdata)
83+
84+
result = deserializer_factory(media_type)(value)
85+
86+
assert result == {'param1': b'test'}
87+
5088
def test_custom_simple(self, deserializer_factory):
5189
custom_mimetype = 'application/custom'
5290
media_type = MediaType(custom_mimetype)

0 commit comments

Comments
 (0)