class FTW::WebServer

An attempt to invent a simple FTW web server.

Public Class Methods

new(host, port, &block) click to toggle source
# File lib/ftw/webserver.rb, line 12
def initialize(host, port, &block)
  @host = host
  @port = port
  @handler = block

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

Public Instance Methods

handle_connection(connection) click to toggle source

Handle a new connection.

This method parses http requests and passes them on to handle_request

@param connection The FTW::Connection being handled.

# 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) click to toggle source

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

# 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
logger() click to toggle source

Get the logger.

# File lib/ftw/webserver.rb, line 99
def logger
  if @logger.nil?
    @logger = Cabin::Channel.get
  end
  return @logger
end
run() click to toggle source

Run the server.

Connections are farmed out to threads.

# 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
stop() click to toggle source
# File lib/ftw/webserver.rb, line 34
def stop
  @server.stop unless @server.nil?
  @threads.each(&:join)
end