Как вызвать метод HTTP POST через SSL в ruby?

Итак, вот запрос с использованием 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 неподдерживаемую ошибку типа носителя.

Ответы на вопрос(4)

Там очень хорошее объяснение того, как сделать запрос 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 состоит в том, что запрос curl отправляет JSON (application-type application / json) к конечной точке, тогда какrequest.set_form_data собирается отправить форму в теле запроса POST (application-type application / x-www-form-urlencoded). Вы должны убедиться, что контент, идущий в обе стороны, имеет тип application / json.

Другой пример:

#!/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
Решение Вопроса

Вы близко, но не совсем там. Попробуйте что-то вроде этого:

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'}}
response = http.request(request)

Это установит заголовок Content-Type, а также опубликует JSON в теле, а не в данных формы, как это было в вашем коде. С примерами учетных данных, это все еще терпит неудачу, но я подозреваю, что это должно работать с реальными данными там.

 13 нояб. 2014 г., 21:05
Я предложил изменить для.to_json в концеrequest.body строка, чтобы избежать ошибок кодирования. Спасибо за отличный ответ!
 NielMalhotra07 июн. 2012 г., 02:03
Это сработало отлично. Спасибо!
 08 мар. 2017 г., 21:44
Пожалуйста, будьте осторожны при использованииOpenSSL::SSL::VERIFY_NONE вводит поток безопасности. Вы уязвимы дляman-in-the-middle attack пропустив проверку сертификата SSL.
 25 дек. 2013 г., 10:32
Можете ли вы помочь мне с этим вопросом:stackoverflow.com/questions/20771177/…
 20 мар. 2015 г., 22:17
Потрясающие! У меня ушло навсегда, чтобы найти это решение, но, к счастью, я нашел этот пост.

Все остальные слишком длинныONE LINER:

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'

ИЛИ если хочешь

NOT verify the hosts be more readable ensure the connection is closed once you're done

затем:

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 options are per connection so you specify them while opening the connection. You can reuse the connection for multiple REST calls to same base url. Think of thread safety of course. Header is a "request header" and hence specified per request. I.e. in calls to get/post/patch/.... HTTP.start(): Creates a new Net::HTTP object, then additionally opens the TCP connection and HTTP session. HTTP.new(): Creates a new Net::HTTP object without opening a TCP connection or HTTP session.

Ваш ответ на вопрос