2010-03-10 28 views
5

Tôi muốn tạo một máy chủ web cực kỳ đơn giản cho các mục đích phát triển trong Ruby (không, không muốn sử dụng các giải pháp đã sẵn sàng).Viết một máy chủ web đơn giản trong Ruby

Đây là mã:

#!/usr/bin/ruby 

require 'socket' 

server = TCPServer.new('127.0.0.1', 8080) 

while connection = server.accept 
    headers = [] 
    length = 0 

    while line = connection.gets 
    headers << line 

    if line =~ /^Content-Length:\s+(\d+)/i 
     length = $1.to_i 
    end 

    break if line == "\r\n" 
    end 

    body = connection.readpartial(length) 

    IO.popen(ARGV[0], 'r+') do |script| 
    script.print(headers.join + body) 
    script.close_write 
    connection.print script.read 
    end 

    connection.close 
end 

Ý tưởng là để chạy kịch bản này từ dòng lệnh, cung cấp một kịch bản khác, mà sẽ nhận được yêu cầu trên đầu vào tiêu chuẩn của nó, và đưa ra phía sau phản ứng đầy đủ về nó đầu ra tiêu chuẩn.

Cho đến nay rất tốt, nhưng điều này hóa ra là thực sự mong manh, vì nó phá vỡ theo yêu cầu thứ hai với các lỗi:

/usr/bin/serve:24:in `write': Broken pipe (Errno::EPIPE) 
    from /usr/bin/serve:24:in `print' 
    from /usr/bin/serve:24 
    from /usr/bin/serve:23:in `popen' 
    from /usr/bin/serve:23 

Bất kỳ ý tưởng làm thế nào để cải thiện mã trên là đủ để sử dụng dễ dàng ?

phiên bản: Ubuntu 9.10 (2.6.31-20-generic), Ruby 1.8.7 (2009/06/12 patchlevel 174) [i486-linux]

+0

Joó, Vì bạn và tôi đang nhận được các kết quả khác nhau như vậy, có lẽ bạn nên thêm vào câu hỏi của bạn các phiên bản Ruby và OS của bạn. –

+0

Tôi đã thêm các phiên bản. –

Trả lời

4

Vấn đề dường như là trong kịch bản trẻ em, kể từ khi kịch bản mẹ trong câu hỏi của bạn chạy trên hộp của tôi (Debian Squeeze, Ruby 1.8.7 patchlevel 249):

tôi tạo ra các hình nộm kịch bản con bar.rb:

#!/usr/bin/ruby1.8 

s = $stdin.read 
$stderr.puts s 
print s 

sau đó tôi chạy kịch bản của bạn, truyền cho nó đường dẫn đến kịch bản giả:

$ /tmp/foo.rb /tmp/bar.rb 

Các tôi nhấn nó với wget:

$ wget localhost:8080/index 

Và thấy đầu ra kịch bản giả của:

GET /index HTTP/1.0^M 
User-Agent: Wget/1.12 (linux-gnu)^M 
Accept: */*^M 
Host: localhost:8080^M 
Connection: Keep-Alive^M 
^M 

Tôi cũng thấy rằng wget nhận những gì nó gửi:

$ cat index 
GET /index HTTP/1.0 
User-Agent: Wget/1.12 (linux-gnu) 
Accept: */* 
Host: localhost:8080 
Connection: Keep-Alive 

Nó làm việc cho dù có bao nhiêu lần tôi đánh nó với wget.

+0

Tôi đã thử kịch bản con của bạn và nó đã ném một lỗi cho lần chạy đầu tiên. Có thể một số khác biệt ở cấp độ hệ điều hành ở đây. –

+0

OK, tôi đã tìm thấy vấn đề nằm ở đâu. Đó là trong kịch bản con: Tôi chỉ in ra một phản ứng HTTP cơ bản, trong khi bạn đã đọc stdin đầu tiên. Bây giờ câu hỏi là tại sao nó là cần thiết để làm như vậy. –

Các vấn đề liên quan