Как заставить Ruby RestClient gem уважать content_type в сообщении?
Например, в консоли RestClient:
RestClient.post 'http://localhost:5001', {:a => 'b'}, :content_type => 'application/json'
Это не отправляет application/json в качестве типа содержимого. Вместо этого я вижу:
Content-Type: application/x-www-form-urlencoded
Мне удалось проследить изменение в restclient/payload.rb:
class UrlEncoded < Base
...
def headers
super.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
end
end
Замена super.merge на super приводит к тому, что тип контента должен соблюдаться, но, очевидно, это не настоящее решение. Кто-нибудь знает, как правильно это исправить? Спасибо.
Ответы
Ответ 1
Возможно, вы захотите поставить json как строку как свою полезную нагрузку вместо хэша. Например, do:
RestClient.post 'http://localhost:5001','{"a":"b"}',:content_type => 'application/json'
Если вы посмотрите на payload.rb, он покажет, что он будет использовать базовую клану вместо класса UrlEncoded, если полезная нагрузка является строкой. Попробуйте это и посмотрите, работает ли это для вас.
Ответ 2
Факт
Для запроса :post
, когда payload
является Hash
, заголовок Content-Type
всегда будет переопределен на application/x-www-form-urlencoded
.
Восстанавливается с помощью rest-client (2.0.0).
Решение
Преобразование хэш-полезной нагрузки в строку json.
require 'json'
payload.to_json
В репозитории rest-client есть :
Ответ 3
Я хотел бы добавить, что моя проблема заключалась в использовании RestClient::Request.execute
(в отличие от RestClient.post
или RestClient.get
).
Проблема заключалась в том, как я устанавливал :content_type
и :accept
. Из примеров, которые я видел, казалось, что они должны быть такими, как:
res = RestClient::Request.execute(
:method => :get,
:url => url,
:verify_ssl => false,
:content_type => :json,
:accept => :json,
:headers => {
:Authorization => "Bearer #{token}",
},
:payload => '{"a":"b"}'
)
Но вы действительно должны помещать их в :headers
следующим образом:
res = RestClient::Request.execute(
:method => :get,
:url => url,
:verify_ssl => false,
:headers => {
:Authorization => "Bearer #{token}",
:content_type => :json,
:accept => :json
},
:payload => '{"a":"b"}'
)
Ответ 4
Я пытался отправить имя пользователя и пароль, наряду с токенами csrf и файлом cookie авторизации, через POST в формате данных формы. Преобразование полезной нагрузки в json и явная настройка заголовка типа контента не помогли. В итоге я передал полезную нагрузку в виде строки запроса и удалил ее преобразование в 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}
)
Другой вариант также будет использовать encode_www_form, но строка запроса лучше подходит для моего конкретного случая использования.
Хотя это не распространенный случай и все зависит от формата параметров, ожидаемого серверной частью, все же целесообразно передать строку запроса в теле POST, если сервер ожидает кодирование URL в качестве тела POST. Надеюсь, это может кому-то помочь.