Как вызвать метод HTTP POST через SSL в рубине?
Итак, здесь запрос с использованием curl:
curl -XPOST -H content-type:application/json -d "{\"credentials\":{\"username\":\"username\",\"key\":\"key\"}}" https://auth.api.rackspacecloud.com/v1.1/auth
Я пытаюсь сделать этот же запрос с помощью ruby, но я не могу заставить его работать.
Я тоже попробовал несколько библиотек, но я не могу заставить его работать.
Вот что я до сих пор:
uri = URI.parse("https://auth.api.rackspacecloud.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new("/v1.1/auth")
request.set_form_data({'credentials' => {'username' => 'username', 'key' => 'key'}})
response = http.request(request)
Я получаю 415 неподдерживаемую ошибку типа носителя.
Ответы
Ответ 1
Вы близко, но не совсем там. Попробуйте что-то вроде этого:
uri = URI.parse("https://auth.api.rackspacecloud.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new("/v1.1/auth")
request.add_field('Content-Type', 'application/json')
request.body = {'credentials' => {'username' => 'username', 'key' => 'key'}}.to_json
response = http.request(request)
Это установит заголовок Content-Type, а также опубликует JSON в теле, а не в данных формы, как это было в вашем коде. С примерами учетных данных, это все еще терпит неудачу, но я подозреваю, что это должно работать с реальными данными там.
Ответ 2
Там очень хорошее объяснение того, как сделать запрос JSON POST с Net:: HTTP по этой ссылке.
Я бы рекомендовал использовать библиотеку, например HTTParty. Он хорошо документирован, вы можете просто настроить свой класс следующим образом:
class RackSpaceClient
include HTTParty
base_uri "https://auth.api.rackspacecloud.com/"
format :json
headers 'Accept' => 'application/json'
#methods to do whatever
end
Похоже, что основное различие между указанным здесь кодом Ruby и запросом на завивки заключается в том, что запрос curl представляет собой POSTing JSON (application-type application/json) для конечной точки, тогда как request.set_form_data
собирается отправить форма в теле запроса POST (приложение типа контента /x -www-form-urlencoded). Вы должны убедиться, что контент, идущий в обоих направлениях, имеет тип application/json.
Ответ 3
Другой пример:
#!/usr/bin/ruby
require 'net/http'
require 'json'
require 'uri'
full_url = "http://" + options[:artifactory_url] + "/" + "api/build/promote/" + options[:build]
puts "Artifactory url: #{full_url}"
data = {
status: "staged",
comment: "Tested on all target platforms.",
ciUser: "builder",
#timestamp: "ISO8601",
dryRun: false,
targetRepo: "#{options[:target]}",
copy: true,
artifacts: true,
dependencies: false,
failFast: true,
}
uri = URI.parse(full_url)
headers = {'Content-Type' => "application/json", 'Accept-Encoding'=> "gzip,deflate",'Accept' => "application/json" }
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, headers)
request.basic_auth(options[:user], options[:password])
request.body = data.to_json
response = http.request(request)
puts response.code
puts response.body
Ответ 4
Все остальные слишком длинны здесь ОДИН ЛИНИЯ:
Net::HTTP.start('auth.api.rackspacecloud.com', :use_ssl => true).post(
'/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json,
initheader={'Content-Type' => 'application/json'}
)
* to_json
требуется require 'json'
ИЛИ если вы хотите
- НЕ проверить хосты
- более читабельны
- убедитесь, что соединение закрыто, как только вы закончите.
то
ssl_opts={:use_ssl => true, :verify_mode => OpenSSL::SSL::VERIFY_NONE}
Net::HTTP.start('auth.api.rackspacecloud.com', ssl_opts) { |secure_connection|
secure_connection.post(
'/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json,
initheader={'Content-Type' => 'application/json'}
)
}
Если вам сложно запомнить, какие параметры идут туда, где:
- Параметры SSL для каждого соединения, поэтому вы указываете их при открытии соединения.
- Вы можете повторно использовать соединение для нескольких вызовов REST на одном базовом URL-адресе. Подумайте о безопасности потоков, конечно.
- Заголовок - это "заголовок запроса" и, следовательно, указан для каждого запроса. То есть при вызовах
get
/post
/patch
/...
.
-
HTTP.start()
: Создает новый объект Net:: HTTP, затем дополнительно открывает соединение TCP и HTTP-сеанс.
-
HTTP.new()
: Создает новый объект Net:: HTTP без открытия TCP-соединения или сеанса HTTP.