Skip to content

Commit 4304002

Browse files
committed
Add content_type property to File
Makes all headers lower case, fixing case sensitivity issues. Exposes jheaders property in Files and Fields.
1 parent 64e9603 commit 4304002

12 files changed

+138
-12
lines changed

multipart/multipart.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ def set_none(self) -> None:
7474
...
7575

7676
class FileProtocol(_FormProtocol, Protocol):
77-
def __init__(self, file_name: bytes | None, field_name: bytes | None, headers: dict[str,bytes], config: FileConfig) -> None:
77+
def __init__(self, file_name: bytes | None, field_name: bytes | None, config: FileConfig,
78+
headers: dict[str,bytes]) -> None:
7879
...
7980

8081
OnFieldCallback = Callable[[FieldProtocol], None]
@@ -353,7 +354,8 @@ class File:
353354
config: The configuration for this File. See above for valid configuration keys and their corresponding values.
354355
""" # noqa: E501
355356

356-
def __init__(self, file_name: bytes | None, field_name: bytes | None = None, headers: dict[str,bytes] = {}, config: FileConfig = {}) -> None:
357+
def __init__(self, file_name: bytes | None, field_name: bytes | None = None,
358+
headers: dict[str,bytes] = {}, config: FileConfig = {}) -> None:
357359
# Save configuration, set other variables default.
358360
self.logger = logging.getLogger(__name__)
359361
self._config = config
@@ -423,6 +425,14 @@ def headers(self) -> dict[str,bytes]:
423425
"""
424426
return self._headers
425427

428+
@property
429+
def content_type(self) -> bytes:
430+
"""The Content-Type value for this part.
431+
"""
432+
if self._headers is None:
433+
return None
434+
return self._headers.get("content-type", None)
435+
426436
def flush_to_disk(self) -> None:
427437
"""If the file is already on-disk, do nothing. Otherwise, copy from
428438
the in-memory buffer to a disk file, and then reassign our internal
@@ -1651,7 +1661,7 @@ def on_header_value(data: bytes, start: int, end: int) -> None:
16511661
header_value.append(data[start:end])
16521662

16531663
def on_header_end() -> None:
1654-
headers[b"".join(header_name)] = b"".join(header_value)
1664+
headers[b"".join(header_name).decode().lower()] = b"".join(header_value)
16551665
del header_name[:]
16561666
del header_value[:]
16571667

@@ -1661,8 +1671,7 @@ def on_headers_finished() -> None:
16611671
is_file = False
16621672

16631673
# Parse the content-disposition header.
1664-
# TODO: handle mixed case
1665-
content_disp = headers.get(b"Content-Disposition")
1674+
content_disp = headers.get("content-disposition")
16661675
disp, options = parse_options_header(content_disp)
16671676

16681677
# Get the field and filename.
@@ -1672,15 +1681,15 @@ def on_headers_finished() -> None:
16721681

16731682
# Create the proper class.
16741683
if file_name is None:
1675-
f = FieldClass(field_name)
1684+
f = FieldClass(field_name, headers=headers)
16761685
else:
1677-
f = FileClass(file_name, field_name, config=self.config)
1686+
f = FileClass(file_name, field_name, config=self.config, headers=headers)
16781687
is_file = True
16791688

16801689
# Parse the given Content-Transfer-Encoding to determine what
16811690
# we need to do with the incoming data.
16821691
# TODO: check that we properly handle 8bit / 7bit encoding.
1683-
transfer_encoding = headers.get(b"Content-Transfer-Encoding", b"7bit")
1692+
transfer_encoding = headers.get("content-transfer-encoding", b"7bit")
16841693

16851694
if transfer_encoding in (b"binary", b"8bit", b"7bit"):
16861695
writer = f

tests/test_data/http/almost_match_boundary.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ expected:
33
- name: file
44
type: file
55
file_name: test.txt
6+
content_type: text/plain
67
data: !!binary |
78
LS1ib3VuZGFyaQ0KLS1ib3VuZGFyeXEtLWJvdW5kYXJ5DXEtLWJvdW5kYXJxDQotLWJvdW5hcnlkLS0NCi0tbm90Ym91bmQtLQ0KLS1taXNtYXRjaA0KLS1taXNtYXRjaC0tDQotLWJvdW5kYXJ5LVENCi0tYm91bmRhcnkNUS0tYm91bmRhcnlR
89

tests/test_data/http/base64_encoding.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ expected:
33
- name: file
44
type: file
55
file_name: test.txt
6+
content_type: text/plain
67
data: !!binary |
78
VGVzdCAxMjM=
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
------WebKitFormBoundarygbACTUR58IyeurVf
2+
Content-Disposition: form-data; name="file1"; filename="test1.txt"
3+
Content-Type: text/plain
4+
5+
Test file #1
6+
------WebKitFormBoundarygbACTUR58IyeurVf
7+
CONTENT-DISPOSITION: form-data; name="file2"; filename="test2.txt"
8+
CONTENT-Type: text/plain
9+
10+
Test file #2
11+
------WebKitFormBoundarygbACTUR58IyeurVf
12+
content-disposition: form-data; name="file3"; filename="test3.txt"
13+
content-type: text/plain
14+
15+
Test file #3
16+
------WebKitFormBoundarygbACTUR58IyeurVf
17+
cOnTenT-DiSpOsItiOn: form-data; name="file4"; filename="test4.txt"
18+
Content-Type: text/plain
19+
20+
Test file #4
21+
------WebKitFormBoundarygbACTUR58IyeurVf--
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
boundary: ----WebKitFormBoundarygbACTUR58IyeurVf
2+
expected:
3+
- name: file1
4+
type: file
5+
file_name: test1.txt
6+
content_type: text/plain
7+
data: !!binary |
8+
VGVzdCBmaWxlICMx
9+
- name: file2
10+
type: file
11+
file_name: test2.txt
12+
content_type: text/plain
13+
data: !!binary |
14+
VGVzdCBmaWxlICMy
15+
- name: file3
16+
type: file
17+
file_name: test3.txt
18+
content_type: text/plain
19+
data: !!binary |
20+
VGVzdCBmaWxlICMz
21+
- name: file4
22+
type: file
23+
file_name: test4.txt
24+
content_type: text/plain
25+
data: !!binary |
26+
VGVzdCBmaWxlICM0

tests/test_data/http/header_with_number.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ expected:
33
- name: files
44
type: file
55
file_name: secret.txt
6+
content_type: "text/plain; charset=utf-8"
67
data: !!binary |
78
YWFhYWFh

tests/test_data/http/multiple_files.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ expected:
33
- name: file1
44
type: file
55
file_name: test1.txt
6+
content_type: 'text/plain'
67
data: !!binary |
78
VGVzdCBmaWxlICMx
89
- name: file2
910
type: file
1011
file_name: test2.txt
12+
content_type: 'text/plain'
1113
data: !!binary |
1214
VGVzdCBmaWxlICMy
1315

tests/test_data/http/quoted_printable_encoding.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ expected:
33
- name: file
44
type: file
55
file_name: test.txt
6+
content_type: 'text/plain'
67
data: !!binary |
78
Zm9vPWJhcg==

tests/test_data/http/single_field_single_file.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ boundary: boundary
22
expected:
33
- name: field
44
type: field
5+
content_type: 'text/plain'
56
data: !!binary |
67
dGVzdDE=
78
- name: file
89
type: file
910
file_name: file.txt
11+
content_type: 'text/plain'
1012
data: !!binary |
1113
dGVzdDI=
1214

tests/test_data/http/single_file.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ expected:
33
- name: file
44
type: file
55
file_name: test.txt
6+
content_type: 'text/plain'
67
data: !!binary |
78
VGhpcyBpcyBhIHRlc3QgZmlsZS4=
89

0 commit comments

Comments
 (0)