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.
python python-requests robotframework
add a comment |
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.
python python-requests robotframework
add a comment |
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.
python python-requests robotframework
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.
python python-requests robotframework
python python-requests robotframework
edited Nov 26 '18 at 8:46
Al Imran
671416
671416
asked Nov 24 '18 at 22:37
juan noguerajuan noguera
45126
45126
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
Thanks a lot Todor. The RequestsLibrary needs some work on documentation, so I was checking the actual python implementation when I got your comprehensive valid answer.
– juan noguera
Nov 25 '18 at 13:25
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462955%2frobotframework-request-how-to-make-a-post-request-with-content-multipart-form%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
Thanks a lot Todor. The RequestsLibrary needs some work on documentation, so I was checking the actual python implementation when I got your comprehensive valid answer.
– juan noguera
Nov 25 '18 at 13:25
add a comment |
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.
Thanks a lot Todor. The RequestsLibrary needs some work on documentation, so I was checking the actual python implementation when I got your comprehensive valid answer.
– juan noguera
Nov 25 '18 at 13:25
add a comment |
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.
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.
edited Nov 25 '18 at 10:55
answered Nov 25 '18 at 10:49
Todor MinakovTodor Minakov
6,23112136
6,23112136
Thanks a lot Todor. The RequestsLibrary needs some work on documentation, so I was checking the actual python implementation when I got your comprehensive valid answer.
– juan noguera
Nov 25 '18 at 13:25
add a comment |
Thanks a lot Todor. The RequestsLibrary needs some work on documentation, so I was checking the actual python implementation when I got your comprehensive valid answer.
– juan noguera
Nov 25 '18 at 13:25
Thanks a lot Todor. The RequestsLibrary needs some work on documentation, so I was checking the actual python implementation when I got your comprehensive valid answer.
– juan noguera
Nov 25 '18 at 13:25
Thanks a lot Todor. The RequestsLibrary needs some work on documentation, so I was checking the actual python implementation when I got your comprehensive valid answer.
– juan noguera
Nov 25 '18 at 13:25
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462955%2frobotframework-request-how-to-make-a-post-request-with-content-multipart-form%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown