class Nile::HttpServer

Attributes

bind_address[RW]
cb[RW]
port[RW]

Public Class Methods

new(address, port, cb) click to toggle source
# File lib/nile/httpd.rb, line 11
def initialize (address, port, cb)
    @bind_address = address
    @port = port
    @cb = cb
end

Public Instance Methods

read_request(sock) click to toggle source
# File lib/nile/httpd.rb, line 54
def read_request sock
    data = sock.recv 1024
    data =~ /Content-Length: (\d+)/
    content_len = $1.to_i
    split_point = data.index "\r\n\r\n"

    while data.length - split_point - 4 < content_len
        data += sock.recv 1024
    end

    headers = data[0..split_point-1].split("\r\n")
    first = headers[0]
    headers.delete_at(0)
    first =~ /(\w+)\ ([\w|\/|\?|\-|\=|\&]+)\ HTTP\//
    verb = $1
    url = $2

    headers_by_key = {}
    headers.each do |header|
        header =~ /^([\w|\-]+): (.*)/
        headers_by_key[$1] = $2
    end

    sock_domain, remote_port, remote_hostname, remote_ip = sock.peeraddr
    {:verb => verb, :url => url, :headers => headers_by_key, :body => data[split_point+4..data.length], :remote_ip => remote_ip, :remote_port => remote_port, :len => content_len, :overall_len => data.length}
end
serve() click to toggle source
# File lib/nile/httpd.rb, line 17
def serve
    webserver = TCPServer.new(@bind_address, @port)
    print "HttpServer running at http://#{@bind_address}:#{@port}\n"

    while (client = webserver.accept)

        Thread.start(client) do |client|
            start = Time.new
            req = read_request client
            http_messages = {
                200 => 'OK',
                204 => 'No Content',
                301 => 'Moved Permanently',
                302 => 'Found',
                401 => 'Unauthorized',
                403 => 'Forbidden',
                404 => 'Not Found',
                500 => 'Internal Server Error'
            }
            response = @cb.handle req, client
            finish = Time.new

            print "handling request #{req[:url]} from #{req[:remote_ip]}:#{req[:remote_port]} (#{req[:len]} bytes) --> replying #{response[0]} #{http_messages[response[0]]} (#{response[2].join("\n").length} bytes) in #{((finish - start) * 1000.0).round(2)} ms\n"

            client.write "HTTP/1.1 #{response[0]} #{http_messages[response[0]]}\r\n"
            response[1].each do |k,v|
                client.write "#{k}: #{v}\r\n"
            end
            client.write "\r\n" + response[2].join("\n")

            client.close
        end

    end

end