如何让 Sinatra 与 HTTPClient 一起工作?
我正在尝试创建一个外观 API,它通过 Sinatra 接收请求,然后在后端的 Github API 上启动 HTTP 请求.
I'm trying to create a facade API that receives requests via Sinatra then launches HTTP requests on Github API in the backend.
在我的hello world"脚本中:
In my "hello world" script I have:
#!/usr/bin/ruby
require 'httpclient'
require 'sinatra'
get '/foo' do
"hello world"
end
但是,它遇到了如下错误:
However, it runs into errors like:
$ ./api.rb
/usr/local/share/gems/gems/sinatra-1.4.3/lib/sinatra/base.rb:1408:in `run!': undefined method `run' for HTTP:Module (NoMethodError)
from /usr/local/share/gems/gems/sinatra-1.4.3/lib/sinatra/main.rb:25:in `block in <module:Sinatra>'
我不明白为什么会发生这种情况.如果我注释掉 require 'httpclient'
行,它就可以正常工作:
I don't understand why this happens. If I comment out the require 'httpclient'
line, it works just fine:
#!/usr/bin/ruby
#require 'httpclient'
require 'sinatra'
get '/foo' do
"hello world"
end
$ ./api.rb
[2013-06-26 21:43:12] INFO WEBrick 1.3.1
[2013-06-26 21:43:12] INFO ruby 1.9.3 (2013-05-15) [x86_64-linux]
[2013-06-26 21:43:12] WARN TCPServer Error: Cannot assign requested address - bind(2)
== Sinatra/1.4.3 has taken the stage on 4567 for development with backup from WEBrick
[2013-06-26 21:43:12] INFO WEBrick::HTTPServer#start: pid=31272 port=4567
我的猜测是 Sinatra 本身正在使用 HTTPClient,并且正在发生某种命名空间冲突.有没有办法同时使用 HTTPClient 和 Sinatra?
My guess is that Sinatra is using HTTPClient by itself and some kind of namespace collision is happening. Is there a way to use HTTPClient and Sinatra at the same time?
好的,这里是请求的信息:
OK here is the requested info:
$ gem list sinatra httpclient
*** LOCAL GEMS ***
sinatra (1.4.3)
$ gem out sinatra httpclient
bigdecimal (1.1.0 < 1.2.0)
io-console (0.3 < 0.4.2)
json (1.6.8 < 1.8.0)
rdoc (3.12 < 4.0.1)
我通过这种方式找出了 httpclient 版本:
I figured out httpclient version this way:
$ locate httpclient.rb
/usr/local/share/gems/gems/httpclient-2.3.3/lib/httpclient.rb
/usr/local/share/gems/gems/httpclient-2.3.3/test/test_httpclient.rb
我的操作系统是 Fedora 17,但不确定是否重要.
My OS is Fedora 17, though not sure if it matters.
我找到了原因.HTTPClient 定义了一个名为 HTTP
的模块.默认情况下,Sinatra 会按照命名空间名称 HTTP
和 WEBrick
的顺序查找 Rack 处理程序.
I found the reason. HTTPClient defines a module named HTTP
. By default Sinatra looks for Rack handlers with namespace names HTTP
and WEBrick
, in that order.
自从定义了 HTTP
命名空间后,Sinatra 实际上认为它是一个 Rack 处理程序.我认为这是 Sinatra 中的一个错误.在使用之前,它应该检查处理程序是否响应 run
.
Since the HTTP
namespace has been defined Sinatra actually thinks it's a Rack handler. I think this is a bug in Sinatra. It should check if the handler responds to run
before using it.
无论如何修复是使用 Thin,或者如果您想使用 WEBrick 然后通过执行以下操作明确告诉 Sinatra 跳过自动机架检测:
Anyway the fix is to use Thin, or if you want to use WEBrick then explicitly tell Sinatra to skip the automatic Rack detection by doing:
set :server, 'webrick'
这将防止 Sinatra 认为 HTTPClient HTTP
模块是 Rack 处理程序.
That will prevent Sinatra from thinking the HTTPClient HTTP
module is Rack handler.