在Ruby中编写一个简单的Web服务器

时间:2010-03-10 13:10:53

标签: ruby webserver

我想在Ruby中创建一个非常简单的Web服务器用于开发目的(不,不想使用现成的解决方案)。

以下是代码:

#!/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

我们的想法是从命令行运行此脚本,提供另一个脚本,该脚本将在其标准输入上获取请求,并在其标准输出上返回完整的响应。

到目前为止一直很好,但事实证明这非常脆弱,因为它在第二个请求中突破了错误:

/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

知道如何改进上述代码以便于使用吗?

版本:Ubuntu 9.10(2.6.31-20-generic),Ruby 1.8.7(2009-06-12 patchlevel 174)[i486-linux]

3 个答案:

答案 0 :(得分:5)

问题似乎出现在子脚本中,因为问题中的父脚本在我的框中运行(Debian Squeeze,Ruby 1.8.7 patchlevel 249):

我创建了虚拟子脚本bar.rb:

#!/usr/bin/ruby1.8

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

然后我运行你的脚本,将它传递给虚拟脚本的路径:

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

我用wget打了它:

$ wget localhost:8080/index

看到虚拟脚本的输出:

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

我也看到wget收到它发送的内容:

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

无论我用wget击打它多少次,它的效果都一样。

答案 1 :(得分:3)

Ruby Web Servers Booklet描述了大多数Web服务器实施策略。

答案 2 :(得分:1)

使用Ruby Webrick Lib,你可以轻松地建立一个网络服务器库。

http://www.ruby-doc.org/stdlib/libdoc/webrick/rdoc/