2013-03-25 70 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