如何在 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 方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Express 应用程序中通过 SSL 获取 websocket?
如何在 ruby on rails 中通过 websocket 发送保持活动的数据包