Class: Nile::HttpServer

Inherits:
Object
  • Object
show all
Defined in:
lib/nile/httpd.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(address, port, cb) ⇒ HttpServer

Returns a new instance of HttpServer.



11
12
13
14
15
# File 'lib/nile/httpd.rb', line 11

def initialize (address, port, cb)
    @bind_address = address
    @port = port
    @cb = cb
end

Instance Attribute Details

#bind_addressObject

Returns the value of attribute bind_address.



9
10
11
# File 'lib/nile/httpd.rb', line 9

def bind_address
  @bind_address
end

#cbObject

Returns the value of attribute cb.



9
10
11
# File 'lib/nile/httpd.rb', line 9

def cb
  @cb
end

#portObject

Returns the value of attribute port.



9
10
11
# File 'lib/nile/httpd.rb', line 9

def port
  @port
end

Instance Method Details

#read_request(sock) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 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

#serveObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 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