class Angelo::Server

Attributes

base[R]

Public Class Methods

define_task(name, &action) click to toggle source
# File lib/angelo/server.rb, line 37
def self.define_task name, &action
  define_method name, &action
end
new(base, addr = nil, port = nil, options = {}) click to toggle source
Calls superclass method
# File lib/angelo/server.rb, line 14
def initialize base, addr = nil, port = nil, options = {}
  @base = base
  addr ||= @base.addr
  port ||= @base.port
  info "Angelo #{VERSION}"
  info "listening on #{addr}:#{port}"
  super addr, port, options, &method(:on_connection)
end
remove_task(name) click to toggle source
# File lib/angelo/server.rb, line 41
def self.remove_task name
  remove_method name
end

Public Instance Methods

on_connection(connection) click to toggle source
# File lib/angelo/server.rb, line 23
def on_connection connection
  # RubyProf.resume
  responders = []

  connection.each_request do |request|
    meth = request.websocket? ? :websocket : request.method.downcase.to_sym
    responder = dispatch! meth, connection, request
    responders << responder if responder and responder.respond_to? :on_close
  end

  responders.each &:on_close
  # RubyProf.pause
end

Private Instance Methods

dispatch!(meth, connection, request) click to toggle source
# File lib/angelo/server.rb, line 47
def dispatch! meth, connection, request
  if staticable?(meth) and lp = @base.local_path(request.path)
    static! meth, connection, request, lp
  else
    route! meth, connection, request
  end
rescue URI::InvalidURIError => e
  Angelo.log meth, connection, request, nil, :bad_request
  connection.respond :bad_request, DEFAULT_RESPONSE_HEADERS, e.message
end
etag_for(local_path) click to toggle source
# File lib/angelo/server.rb, line 115
def etag_for local_path
  fs = File::Stat.new local_path
  OpenSSL::Digest::SHA.hexdigest fs.ino.to_s + fs.size.to_s + fs.mtime.to_s
end
post_override!(meth, request) click to toggle source
# File lib/angelo/server.rb, line 58
def post_override! meth, request
  if meth == :post and request.headers.has_key? POST_OVERRIDE_REQUEST_HEADER_KEY
    new_meth = request.headers[POST_OVERRIDE_REQUEST_HEADER_KEY].downcase.to_sym
    meth = new_meth if POST_OVERRIDABLE.include? new_meth
  end
  meth
rescue
  meth
end
route!(meth, connection, request) click to toggle source
# File lib/angelo/server.rb, line 68
def route! meth, connection, request
  meth = post_override! meth, request
  if rs = @base.routes[meth][request.path]
    responder = rs.dup
    responder.reset!
    responder.base = @base.new responder
    responder.connection = connection
    responder.request = request
    responder.handle_request
    responder
  else
    Angelo.log meth, connection, request, nil, :not_found
    connection.respond :not_found, DEFAULT_RESPONSE_HEADERS, NOT_FOUND
  end
end
sse_event(*a;) click to toggle source
# File lib/angelo/server.rb, line 120
def sse_event *a; Base.sse_event *a; end
sse_message(*a;) click to toggle source
# File lib/angelo/server.rb, line 121
def sse_message *a; Base.sse_message *a; end
static!(meth, connection, request, local_path) click to toggle source
# File lib/angelo/server.rb, line 88
def static! meth, connection, request, local_path
  etag = etag_for local_path
  if request.headers[IF_NONE_MATCH_HEADER_KEY] == etag
    Angelo.log meth, connection, request, nil, :not_modified, 0
    connection.respond :not_modified
  else
    headers = {

      # Content-Type
      #
      CONTENT_TYPE_HEADER_KEY =>
        (MIME::Types.type_for(File.extname(local_path))[0].content_type rescue HTML_TYPE),

      # Content-Length
      #
      CONTENT_LENGTH_HEADER_KEY => File.size(local_path),

      # ETag
      #
      ETAG_HEADER_KEY => etag

    }
    Angelo.log meth, connection, request, nil, :ok, headers[CONTENT_LENGTH_HEADER_KEY]
    connection.respond :ok, headers, (meth == :head ? nil : File.read(local_path))
  end
end
staticable?(meth) click to toggle source
# File lib/angelo/server.rb, line 84
def staticable? meth
  STATICABLE.include? meth
end