Robotframework.request - How to make a POST request with content “multipart/form-data”

感情迁移 提交于 2020-02-02 06:35:05

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/53462955/robotframework-request-how-to-make-a-post-request-with-content-multipart-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!