Reputation: 3588
For instance, in the RestClient console:
RestClient.post 'http://localhost:5001', {:a => 'b'}, :content_type => 'application/json'
This does not send application/json as the content type. Instead I see:
Content-Type: application/x-www-form-urlencoded
I was able to trace the change to restclient/payload.rb:
class UrlEncoded < Base
...
def headers
super.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
end
end
Replacing super.merge with super causes the content type to be respected, but obviously that's not a real solution. Does anyone know the proper way to fix this? Thanks.
Upvotes: 18
Views: 20968
Reputation: 905
I was trying to submit username and password, alongside csrf tokens and auth cookie, via POST in form data format. Payload conversion to json and explicitly setting content-type header did not help. I ended up passing payload as a query string and removed its conversion to JSON:
RestClient::Request.execute(
method: :post,
url: 'http://app_url/login.do',
payload: "username=username&password=password&_csrf=token",
headers: {'X-XSRF-TOKEN' => 'token'},
cookies: {'XSRF-TOKEN' => cookie_object}
)
Another option would also be to use encode_www_form, but a query string works better for my specific use case.
While this is not a common case and all depends on parameter format expected by the back end, it's still a viable option to pass a query string in the POST body if the server expects url encoding as POST body. Hopefully this might help someone.
Upvotes: 1
Reputation: 15116
Fact:
For :post
request, when payload
is a Hash
, the Content-Type
header will be always overridden to application/x-www-form-urlencoded
.
Reproduciable with rest-client (2.0.0).
Solution:
Convert the hash payload to json string.
require 'json'
payload.to_json
There is a ticket in rest-client's repo:
Upvotes: 18
Reputation: 1862
I'd like to add that my issue was when using RestClient::Request.execute
(as opposed to RestClient.post
or RestClient.get
).
The problem was with how I was setting :content_type
and :accept
. From the examples I saw it felt like they should be top level options like this:
res = RestClient::Request.execute(
:method => :get,
:url => url,
:verify_ssl => false,
:content_type => :json,
:accept => :json,
:headers => {
:Authorization => "Bearer #{token}",
},
:payload => '{"a":"b"}'
)
But you actually have to put them within :headers
like this:
res = RestClient::Request.execute(
:method => :get,
:url => url,
:verify_ssl => false,
:headers => {
:Authorization => "Bearer #{token}",
:content_type => :json,
:accept => :json
},
:payload => '{"a":"b"}'
)
Upvotes: 11
Reputation: 681
You might want to put json as string as your payload instead of hash. For example, do:
RestClient.post 'http://localhost:5001','{"a":"b"}',:content_type => 'application/json'
If you look at the payload.rb, it shows that it will use the Base clase instead of UrlEncoded class if the payload is string. Try that and see if that work for you.
Upvotes: 24