Вопрос по ruby, https – Как вызвать метод HTTP POST через SSL в ruby?

34

Итак, вот запрос с использованием 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   ответа
2

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

#!/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
58

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

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

Потрясающие! У меня ушло навсегда, чтобы найти это решение, но, к счастью, я нашел этот пост.
Я предложил изменить для.to_json в концеrequest.body строка, чтобы избежать ошибок кодирования. Спасибо за отличный ответ!
Это сработало отлично. Спасибо! NielMalhotra
Пожалуйста, будьте осторожны при использованииOpenSSL::SSL::VERIFY_NONE вводит поток безопасности. Вы уязвимы дляman-in-the-middle attack пропустив проверку сертификата SSL.
Можете ли вы помочь мне с этим вопросом:stackoverflow.com/questions/20771177/…
3

Все остальные слишком длинны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.
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.

Похожие вопросы