2013-03-25 71 views
1

现在我尝试连接到我的插座由麒麟cretaed与此代码红宝石1.9.3简单的GET请求,麒麟通过插座

require 'socket' 

def foo 
    socket = UNIXSocket.new("path_to_socket/tmp/unicorn.sock") 

    data = "GET /time HTTP/1.1\n" 
    data << "Connection: Close\n" 
    data << "User-Agent: Mozilla/5.0\n" 
    data << "Accept: */*\n" 
    data << "Content-Type: application/x-www-form-urlencoded\n" 
    data << "\n\r\n\r" 

    socket.puts(data) 

    while(line = socket.gets) do 
    puts line 
    end 
end 

foo 

但总是得到一个“HTTP/1.1 400错误的请求”

请,任何机构可以说我做错了吗?

+1

由于其他人已经指出了不涉及编写自己请求的替代方案,因此我会尽量总结您提出的请求出了什么问题。 1:你的标题由'\ n'终止;它们实际上应该由'\ r \ n'终止。 2:以类似的方式,您应该使用'\ r \ n \ r \ n',而不是'\ n \ r \ n \ r'来终止您的请求。 3:每个服务器我都会在需要的时候抛出一个手写的HTTP请求,甚至那些实际上并没有给出它的值的东西 - 也就是'Host:localhost'的行'应该在​​你的情况下工作得很好。 – javawizard 2015-03-05 08:04:13

回答

5

使用net/HTTP ...

require "net/http" 
require "socket" 

sock = Net::BufferedIO.new(UNIXSocket.new("path_to_socket/tmp/unicorn.sock")) 
request = Net::HTTP::Get.new("/time") 
request.exec(sock, "1.1", "/time") 

begin 
    response = Net::HTTPResponse.read_new(sock) 
end while response.kind_of?(Net::HTTPContinue) 
response.reading_body(sock, request.response_body_permitted?) { } 

response.body 
response.code 
+0

是它的工作原理,非常感谢 – Evgenii 2013-03-26 07:21:33

+1

任何人都得到400错误的请求尝试这种时候: 请注意,所有的HTTP/1.1请求必须指定一个'主持人:'头根据RFC 2616对于HTTP/1.0请求的唯一真正的选择是服务“主”主机结果。这个问题特别针对HTTP/1.1协议请求。从问题[14705659](http://stackoverflow.com/questions/14705659/returning-400-in-virtual-host-environments-where-host-header-has-no-match) – 2013-11-28 04:37:01

+0

还要注意的是,HTTPGenericRequest#EXEC ,而它的访问是公开的,它[标记为](http://yard.ruby-doc.org/stdlib-2.0/Net/HTTPGenericRequest.html#exec-instance_method)':nodoc:仅供内部使用',所以它不会在API文档中显示,并可能随时间而改变。 – 2013-11-28 04:43:36

1

这是非常有用的,但请注意的Net :: HTTP#exec方法标记仅供内部使用。可能是因为它没有做资源管理等

以下工作相适应的建议的战略覆盖的Net :: HTTP#连接(连接到插座)。我喜欢使用HTTParty gem来处理我的HTTP请求。所以这里的策略使用了一个用于HTTParty的自定义ConnectionAdaptor。现在,我只需更改我的包含类中的:: default_params = call,以控制我们是使用Unix还是TCP/HTTP套接字。

########################################################### 
# net/socket_http.rb 
########################################################### 

module Net 
    # Overrides the connect method to simply connect to a unix domain socket. 
    class SocketHttp < HTTP 
    attr_reader :socket_path 

    # URI should be a relative URI giving the path on the HTTP server. 
    # socket_path is the filesystem path to the socket the server is listening to. 
    def initialize(uri, socket_path) 
     @socket_path = socket_path 
     super(uri) 
    end 

    # Create the socket object. 
    def connect 
     @socket = Net::BufferedIO.new UNIXSocket.new socket_path 
     on_connect 
    end 

    # Override to prevent errors concatenating relative URI objects. 
    def addr_port 
     File.basename(socket_path) 
    end 
    end 
end 


########################################################### 
# sock_party.rb, a ConnectionAdapter class 
########################################################### 
require "net/http" 
require "socket" 

class SockParty < HTTParty::ConnectionAdapter 
    # Override the base class connection method. 
    # Only difference is that we'll create a Net::SocketHttp rather than a Net::HTTP. 
    # Relies on :socket_path in the 
    def connection 
    http = Net::SocketHttp.new(uri, options[:socket_path]) 

    if options[:timeout] && (options[:timeout].is_a?(Integer) || options[:timeout].is_a?(Float)) 
     http.open_timeout = options[:timeout] 
     http.read_timeout = options[:timeout] 
    end 

    if options[:debug_output] 
     http.set_debug_output(options[:debug_output]) 
    end 

    if options[:ciphers] 
     http.ciphers = options[:ciphers] 
    end 

    return http 
    end 
end 


########################################################### 
# class MockSockParty, a really *nix-y HTTParty 
########################################################### 
class MockSockParty 
    include HTTParty 
    self.default_options = {connection_adapter: SockParty, socket_path: '/tmp/thin.sock'} 

    def party_hard 
    self.class.get('/client').body 
    end 
end 

########################################################### 
# sock_party_spec.rb 
########################################################### 

require 'spec_helper' 

describe SockParty do 
    it "should party until its socks fall off." do 
    puts MockSockParty.new.party_hard 
    end 
end