Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
890 views
in Technique[技术] by (71.8m points)

python - Robotframework.request - How to make a POST request with content "multipart/form-data"

I want to make a POST request in Robot Framework with "Content-Type: multipart/form-data" using the RequestsLibrary but nothing seems to work. The Keyword that makes this request looks as follows:

*** Variables ***
&{API_CREDS}  username=myusername  password=mypwd

*** Keywords ***
Get token
    # Assumes that session has been created
    [Arguments]  ${Session_id}
    &{headers}=  create dictionary  Content-Type=multipart/form-data
    ${response}=  Post Request  ${Session_id}  ${AUTH_TOKEN_URL_PATH}  data=${API_CREDS}   headers=${headers}
    should be equal as integers  ${response.status_code}  200
    [Return]  ${response.json()['token']}

But the POST request that is actually sent does not contain a "Content-Type" header and the body is just a raw data={'username' = 'myusername', ' password' = 'mypwd'}

I have tried many things that I have found searching around but nothing works. Does the RequestsLibrary of Robot Framework actually supports sending a POST request with "Content-Type: multipart/form-data"?, if so how is this done?

PS: I am using Robot Framework on Windows 10 with Python 3.7.1. The POST request is actually sent, but it does not contain a Content-Type header, nor a form-data payload, as mentioned above.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The underlying python library that's used - requests , has some peculiarities working with multipart "form-data" content. It uses it primary for sending files as part of the request (an upload functionality); roughly speaking when it parsed your arguments, it stripped the header because there were no files to be sent. Also, if it didn't do that, it's not designed to deduct what are the different parts in your multipart payload - e.g. it doesn't automatically put every key-value pair in a separate part.

To overcome this, one usually uses the files parameter, passing as argument the content of the different parts. In doing so, the requests library will automatically set the form-data header, and break-up the content in parts.
Here's how to do that in RF, explanation follows:

${data}=    Evaluate    {'username': (None, 'myusername'), 'password': (None, 'mypwd')}
${response}=  Post Request  ${Session_id}  ${AUTH_TOKEN_URL_PATH}  files=${data}

Using the files parameter in the Post Request keyword your payload will be passed to the requests post method as is. You don't need to set the headers explicitly, the library will do it for you.

What is passed as argument is a dictionary, were the values are the parts' content. As you can see the actual values are python tuples, because you want to override the filename in the part. This is better explained with an example; if the data is like this, the value being a simple sting:

${data}=    Evaluate    {'username': 'myusername', 'password': 'mypwd'}

, then the payload will turn up as:

--7579227dh785568ha91866339229add786
Content-Disposition: form-data; name="username"; filename="username"

myusername
--7579227dh785568ha91866339229add786
Content-Disposition: form-data; name="password"; filename="password"

mypwd
--7579227dh785568ha91866339229add786--

Notice how each part has a "filename" property, equal to the parameter name.

When the value is a tuple, its first member sets the "filename" property of the part; and when it is a None, there is no "filename" at all, producing this result:

--7579227dh785568ha91866339229add786
Content-Disposition: form-data; name="username"

myusername
--7579227dh785568ha91866339229add786
Content-Disposition: form-data; name="password"

mypwd
--7579227dh785568ha91866339229add786--

, which is probably your goal.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...