Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

ruby - How do I get Sinatra to work with HTTPClient?

I'm trying to create a facade API that receives requests via Sinatra then launches HTTP requests on Github API in the backend.

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>'

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

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)

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

My OS is Fedora 17, though not sure if it matters.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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.

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'

That will prevent Sinatra from thinking the HTTPClient HTTP module is Rack handler.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...