如何强制Faraday
适配器typhoeus使用 HTTP/2 对支持 HTTP/2 的服务器的请求?我已经通过服务https://http2.pro/doc/api对此进行了测试,结果如下:
body="{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Faraday v0.12.2\"}",
\"http2\":1,
什么意味着 HTTP/2 不用于请求!
这里有两件事在起作用。首先是远程 API 在响应正文中对您撒谎。他们的文件说:
http2:可能的值为 0(使用 HTTP/2)和 1(未使用 HTTP/2)。
尽管响应正文显示'http2': 1
HTTP2 未被使用,但它正在被使用。您可以使用 Chrome 的开发工具轻松确认这一点:
那么一旦我们知道 API 位于响应体中,我们如何独立确认 Typhoeus 使用的是 HTTP2 呢?
(此答案假设您使用pry
的是 REPL,而不是 IRB)
首先让我们确认 Typhoeus 单独使用 HTTP2:
require 'typhoeus'
response = Typhoeus.get("https://http2.pro/api/v1", http_version: :httpv2_0)
response.class
=> Typhoeus::Response < Object
response.body
=> "{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Typhoeus - https:\\/\\/github.com\\/typhoeus\\/typhoeus\"}" # this is the lying API response
response.http_version
=> "2" # this is what Typhoeus tells us was actually used
现在让我们在法拉第测试它:
require 'faraday'
require 'typhoeus'
require 'typhoeus/adapters/faraday'
conn = Faraday.new do |faraday|
faraday.adapter :typhoeus, http_version: :httpv2_0
end
response = conn.get("https://http2.pro/api/v1")
response.body
=> "{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Faraday v0.17.0\"}" # again we get the lying API response
但是我们如何确认它是 HTTP2 呢?这不起作用:
response.http_version
NoMethodError: undefined method `http_version' for #<Faraday::Response:0x00007f99935519a8>
因为response
不是Typhoeus::Response
对象,所以它是法拉第对象:
response.class
=> Faraday::Response < Object
所以我们需要进入 gem 本身来确定它在哪里创建Typhoeus::Response
对象,这样我们就可以手动调用.http_version
它并确认它使用我们期望的协议。事实证明,就在这里。
让我们采取简单的方法并坚持binding.pry
到 gem 的本地副本(您需要重新启动 pry 以获取对 gem 的更改):
def typhoeus_request(env)
opts = {
:method => env[:method],
:body => env[:body],
:headers => env[:request_headers]
}.merge(@adapter_options)
binding.pry
::Typhoeus::Request.new(env[:url].to_s, opts)
end
然后重新运行请求:
require 'faraday'
require 'typhoeus'
require 'typhoeus/adapters/faraday'
conn = Faraday.new do |faraday|
faraday.adapter :typhoeus, http_version: :httpv2_0
end
response = conn.get("https://http2.pro/api/v1")
你会看到:
Frame number: 0/3
From: /Users/foo/.rvm/gems/ruby-2.6.3/gems/typhoeus-1.3.1/lib/typhoeus/adapters/faraday.rb @ line 127 Faraday::Adapter::Typhoeus#typhoeus_request:
120: def typhoeus_request(env)
121: opts = {
122: :method => env[:method],
123: :body => env[:body],
124: :headers => env[:request_headers]
125: }.merge(@adapter_options)
126: binding.pry
=> 127: ::Typhoeus::Request.new(env[:url].to_s, opts)
128: end
现在输入:
response = ::Typhoeus::Request.new(env[:url].to_s, opts).run
并确认它是一个Typhoeus::Response
对象:
response.class
=> Typhoeus::Response < Object
并确认它使用的是 HTTP2:
response.http_version
=> "2"
并确认 API 响应正文是一个肮脏的骗子:
response.body
=> "{\"http2\":1,\"protocol\":\"HTTP\\/2.0\",\"push\":0,\"user_agent\":\"Faraday v0.17.0\"}"
这就是您如何使用 Typhoeus 作为法拉第适配器来发出 HTTP2 请求。