Class: FTW::WebServer

Inherits:
Object
  • Object
show all
Includes:
CRLF, Protocol
Defined in:
lib/ftw/webserver.rb

Overview

An attempt to invent a simple FTW web server.

Constant Summary

Constants included from CRLF

CRLF::CRLF

Instance Method Summary collapse

Methods included from Protocol

#discard_body, #encode_chunked, #read_body, #read_http_body, #read_http_body_chunked, #read_http_body_length, #read_http_message, #write_all, #write_http_body, #write_http_body_chunked, #write_http_body_normal

Constructor Details

#initialize(host, port, &block) ⇒ WebServer

Returns a new instance of WebServer.



12
13
14
15
16
17
18
19
# File 'lib/ftw/webserver.rb', line 12

def initialize(host, port, &block)
  @host = host
  @port = port
  @handler = block

  @logger = Cabin::Channel.get
  @threads = []
end

Instance Method Details

#handle_connection(connection) ⇒ Object

Handle a new connection.

This method parses http requests and passes them on to #handle_request

Parameters:

  • connection

    The FTW::Connection being handled.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/ftw/webserver.rb', line 44

def handle_connection(connection)
  while true
    begin
      request = read_http_message(connection)
    rescue EOFError, Errno::EPIPE, Errno::ECONNRESET, HTTP::Parser::Error, IOError
      # Connection EOF'd or errored before we finished reading a full HTTP
      # message, shut it down.
      break
    rescue FTW::HTTP::Message::UnsupportedHTTPVersion
      break
    end

    if request["Content-Length"] || request["Transfer-Encoding"]
      request.body = connection
    end

    begin
      handle_request(request, connection)
    rescue => e
      puts e.inspect
      puts e.backtrace
      raise e
    end
  end
  connection.disconnect("Fun")
end

#handle_request(request, connection) ⇒ Object

Handle a request. This will set up the rack ‘env’ and invoke the application associated with this handler.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ftw/webserver.rb', line 73

def handle_request(request, connection)
  response = FTW::Response.new
  response.version = request.version
  response["Connection"] = request.headers["Connection"] || "close"

  # Process this request with the handler
  @handler.call(request, response, connection)

  # Write the response
  begin
    connection.write(response.to_s + CRLF)
    if response.body?
      write_http_body(response.body, connection,
                      response["Transfer-Encoding"] == "chunked") 
    end
  rescue => e
    @logger.error(e)
    connection.disconnect(e.inspect)
  end

  if response["Connection"] == "close" or response["Connection"].nil?
    connection.disconnect("'Connection' header was close or nil")
  end
end

#loggerObject

Get the logger.



99
100
101
102
103
104
# File 'lib/ftw/webserver.rb', line 99

def logger
  if @logger.nil?
    @logger = Cabin::Channel.get
  end
  return @logger
end

#runObject

Run the server.

Connections are farmed out to threads.



24
25
26
27
28
29
30
31
32
# File 'lib/ftw/webserver.rb', line 24

def run
  logger.info("Starting server", :config => @config)
  @server = FTW::Server.new([@host, @port].join(":"))
  @server.each_connection do |connection|
    @threads << Thread.new do
      handle_connection(connection)
    end
  end
end

#stopObject

def run



34
35
36
37
# File 'lib/ftw/webserver.rb', line 34

def stop
  @server.stop unless @server.nil?
  @threads.each(&:join)
end