Assume there's an endpoint accepting HTTP
requests with multipart/form-data
content-type. Here's the example of the body of an acceptable request.
----------------------------033392576939750140334380
Content-Disposition: form-data; name="file" filename="dummy_file.txt"
Some dummy file here.
----------------------------033392576939750140334380
Content-Disposition: form-data; name="years"
2019
----------------------------033392576939750140334380
Content-Disposition: form-data; name="years"
2020
----------------------------033392576939750140334380
As you can see, there's an array of numbers that are being sent using years
keyword.
The questions is how can we send the same request using requests
library in python
?
It seems to be pretty tricky because of that years
array.
I've tried to send it these ways.
requests.post(
"http://some.site/some-endpoint/",
files={
"years": [2019, 2020],
"file": ("dummy_file.txt", open("dummy_file.txt", "rb")),
},
)
Not going to work - TypeError: a bytes-like object is required, not 'list'
.
requests.post(
"http://some.site/some-endpoint/",
files={
"years": (None, "2019, 2020"),
"file": ("dummy_file.txt", open("dummy_file.txt", "rb")),
},
)
Gives the following request body.
--88c0aa2588fb3ca9b1e3c9c6cf625677
Content-Disposition: form-data; name="years"
2019, 2020
--88c0aa2588fb3ca9b1e3c9c6cf625677
Content-Disposition: form-data; name="file"; filename="dummy_file.txt"
Some dummy file here.
--88c0aa2588fb3ca9b1e3c9c6cf625677--
The years
array is represented here as the string value which is not okay for this case.
requests.post(
"http://some.site/some-endpoint/",
files={
"years[0]": (None, "2020"),
"years[1]": (None, "2019"),
"file": ("dummy_file.txt", open("dummy_file.txt", "rb")),
},
)
Gives the following request body.
--989f55fc01395402654f4275d11e8735
Content-Disposition: form-data; name="years[0]"
2020
--989f55fc01395402654f4275d11e8735
Content-Disposition: form-data; name="years[1]"
2019
Content-Disposition: form-data; name="file"; filename="dummy_file.txt"
Some dummy file here.
--989f55fc01395402654f4275d11e8735
This way every element in the years
array is represented by a different name
, which is also not suitable for this particular case.
If we examine the last attempt it seems that we can achieve the required body structure by sending each value of years
array using the same years
keyword. But that's not going to work with requests
as the files
attribute accepts dict
object which only allows unique keys.
So, how can we achieve this using requests
module?
CodePudding user response:
I found this in the docs: https://requests.readthedocs.io/en/latest/user/quickstart/#more-complicated-post-requests
Use a list of tuples to create the mapping, not a dict:
r = requests.post(
"https://httpbin.org/anything",
files=[
("file", ("dummy_file.txt", b"File content....")),
("years", (None, 2019)),
("years", (None, 2020)),
]
)
Data sent in r.request.body
:
--8d763b42e4adf30aaefb9657df8bcf1b
Content-Disposition: form-data; name="file"; filename="dummy_file.txt"
File content....
--8d763b42e4adf30aaefb9657df8bcf1b
Content-Disposition: form-data; name="years"
2019
--8d763b42e4adf30aaefb9657df8bcf1b
Content-Disposition: form-data; name="years"
2020
--8d763b42e4adf30aaefb9657df8bcf1b--