1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
from __future__ import annotations
import pytest
from urllib3.fields import (
RequestField,
format_header_param,
format_header_param_html5,
format_header_param_rfc2231,
format_multipart_header_param,
guess_content_type,
)
class TestRequestField:
@pytest.mark.parametrize(
"filename, content_types",
[
("image.jpg", ["image/jpeg", "image/pjpeg"]),
("notsure", ["application/octet-stream"]),
(None, ["application/octet-stream"]),
],
)
def test_guess_content_type(
self, filename: str | None, content_types: list[str]
) -> None:
assert guess_content_type(filename) in content_types
def test_create(self) -> None:
simple_field = RequestField("somename", "data")
assert simple_field.render_headers() == "\r\n"
filename_field = RequestField("somename", "data", filename="somefile.txt")
assert filename_field.render_headers() == "\r\n"
headers_field = RequestField(
"somename", "data", headers={"Content-Length": "4"}
)
assert headers_field.render_headers() == "Content-Length: 4\r\n\r\n"
def test_make_multipart(self) -> None:
field = RequestField("somename", "data")
field.make_multipart(content_type="image/jpg", content_location="/test")
assert (
field.render_headers()
== 'Content-Disposition: form-data; name="somename"\r\n'
"Content-Type: image/jpg\r\n"
"Content-Location: /test\r\n"
"\r\n"
)
def test_make_multipart_empty_filename(self) -> None:
field = RequestField("somename", "data", "")
field.make_multipart(content_type="application/octet-stream")
assert (
field.render_headers()
== 'Content-Disposition: form-data; name="somename"; filename=""\r\n'
"Content-Type: application/octet-stream\r\n"
"\r\n"
)
def test_render_parts(self) -> None:
field = RequestField("somename", "data")
parts = field._render_parts({"name": "value", "filename": "value"})
assert 'name="value"' in parts
assert 'filename="value"' in parts
parts = field._render_parts([("name", "value"), ("filename", "value")])
assert parts == 'name="value"; filename="value"'
@pytest.mark.parametrize(
("value", "expect"),
[("näme", "filename*=utf-8''n%C3%A4me"), (b"name", 'filename="name"')],
)
def test_format_header_param_rfc2231_deprecated(
self, value: bytes | str, expect: str
) -> None:
with pytest.deprecated_call(match=r"urllib3 v2\.1\.0"):
param = format_header_param_rfc2231("filename", value)
assert param == expect
def test_format_header_param_html5_deprecated(self) -> None:
with pytest.deprecated_call(match=r"urllib3 v2\.1\.0"):
param2 = format_header_param_html5("filename", "name")
with pytest.deprecated_call(match=r"urllib3 v2\.1\.0"):
param1 = format_header_param("filename", "name")
assert param1 == param2
@pytest.mark.parametrize(
("value", "expect"),
[
("name", "name"),
("näme", "näme"),
(b"n\xc3\xa4me", "näme"),
("ski ⛷.txt", "ski ⛷.txt"),
("control \x1A\x1B\x1C", "control \x1A\x1B\x1C"),
("backslash \\", "backslash \\"),
("quotes '\"", "quotes '%22"),
("newline \n\r", "newline %0A%0D"),
],
)
def test_format_multipart_header_param(
self, value: bytes | str, expect: str
) -> None:
param = format_multipart_header_param("filename", value)
assert param == f'filename="{expect}"'
def test_from_tuples(self) -> None:
field = RequestField.from_tuples("file", ("スキー旅行.txt", "data"))
cd = field.headers["Content-Disposition"]
assert cd == 'form-data; name="file"; filename="スキー旅行.txt"'
def test_from_tuples_rfc2231(self) -> None:
with pytest.deprecated_call(match=r"urllib3 v2\.1\.0"):
field = RequestField.from_tuples(
"file", ("näme", "data"), header_formatter=format_header_param_rfc2231
)
cd = field.headers["Content-Disposition"]
assert cd == "form-data; name=\"file\"; filename*=utf-8''n%C3%A4me"
|