如何在 ruby​​ 中通过 SSL 调用 HTTP POST 方法?

Posted

技术标签:

【中文标题】如何在 ruby​​ 中通过 SSL 调用 HTTP POST 方法?【英文标题】:How to invoke HTTP POST method over SSL in ruby? 【发布时间】:2012-06-10 18:26:12 【问题描述】:

这是使用 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 发布到正文中,而不是像您的代码那样在表单数据中发布。使用示例凭据,它仍然失败,但我怀疑它应该可以处理那里的真实数据。

【讨论】:

你能帮我解决这个问题吗:***.com/questions/20771177/… 我建议在request.body 行的末尾编辑.to_json 以避免编码错误。不过感谢您的出色回答! 太棒了!我花了很长时间才找到这个解决方案,但幸运的是我找到了这篇文章。 @Eugene 在倒数第二行中,为什么我们要在正文中传递参数。我们不应该将其作为查询参数吗?另外,我想知道如何传递与查询参数相同的参数。 请小心使用OpenSSL::SSL::VERIFY_NONE 会引入安全流程。通过跳过 SSL 证书验证,您很容易受到 man-in-the-middle attack 的攻击。 【参考方案2】:

关于如何使用 Net::HTTP at this link 发出 JSON POST 请求有一个很好的解释。

我建议使用像 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(内容类型应用程序/json)发送到端点,而 request.set_form_data 将发送POST 请求正文中的表单(内容类型应用程序/x-www-form-urlencoded)。您必须确保双向传输的内容是 application/json 类型。

【讨论】:

【参考方案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'


或者如果你愿意

验证主机 更具可读性 确保连接完成后关闭

然后:

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 选项是针对每个连接的,因此您可以在打开连接时指定它们。 您可以将连接重复用于对同一基本 URL 的多个 REST 调用。当然要考虑线程安全。 标头是“请求标头”,因此按请求指定。 IE。在调用get/post/patch/...HTTP.start():创建一个新的 Net::HTTP 对象,然后另外打开 TCP 连接和 HTTP 会话。 HTTP.new():在不打开 TCP 连接或 HTTP 会话的情况下创建一个新的 Net::HTTP 对象。

【讨论】:

【参考方案4】:

另一个例子:

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

【讨论】:

以上是关于如何在 ruby​​ 中通过 SSL 调用 HTTP POST 方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ruby 中通过引用传递?

如何在 Express 应用程序中通过 SSL 获取 websocket?

如何在 ruby​​ on rails 中通过 websocket 发送保持活动的数据包

如何在 Ruby on Rails 中通过关联订购 has_many?

在Ruby中通过十六进制字符串获取unicode [重复]

SSL 证书在 WordPress 更新中通过纯 HTTP(非 SSL)验证失败