lib/stub/server.rb in cf-uaac-1.3.1 vs lib/stub/server.rb in cf-uaac-1.3.3
- old
+ new
@@ -87,12 +87,11 @@
class Reply
attr_accessor :status, :headers, :body
def initialize(status = 200) @status, @headers, @cookies, @body = status, {}, [], "" end
def to_s
reply = "HTTP/1.1 #{@status} OK\r\n"
- headers["server"] = "stub server"
- headers["date"] = DateTime.now.httpdate
+ headers["server"], headers["date"] = "stub server", DateTime.now.httpdate
headers["content-length"] = body.bytesize
headers.each { |k, v| reply << "#{k}: #{v}\r\n" }
@cookies.each { |c| reply << "Set-Cookie: #{c}\r\n" }
reply << "\r\n" << body
end
@@ -166,20 +165,26 @@
def initialize(server)
@server, @request, @reply, @match = server, Request.new, Reply.new, nil
end
+ def default_route; reply_in_kind(404, error: "path not handled") end
+
def process
@reply = Reply.new
+ if server.root
+ return default_route unless request.path.start_with?(server.root)
+ request.path.slice!(0..server.root.length - 1)
+ end
@match, handler = self.class.find_route(request)
server.logger.debug "processing request to path #{request.path} for route #{@match ? @match.regexp : 'default'}"
send handler
reply.headers['connection'] ||= request.headers['connection'] if request.headers['connection']
server.logger.debug "replying to path #{request.path} with #{reply.body.length} bytes of #{reply.headers['content-type']}"
#server.logger.debug "full reply is: #{reply.body.inspect}"
rescue Exception => e
- server.logger.debug "exception from route handler: #{e.message}"
+ server.logger.debug "exception processing request: #{e.message}"
server.trace { e.backtrace }
reply_in_kind 500, e
end
def reply_in_kind(status = nil, info)
@@ -188,14 +193,10 @@
when /text\/html/ then reply.html(status, info)
else reply.text(status, info)
end
end
- def default_route
- reply_in_kind(404, error: "path not handled")
- end
-
end
#------------------------------------------------------------------------------
module Connection
attr_accessor :req_handler
@@ -214,42 +215,66 @@
req_handler.server.trace { e.backtrace }
close_connection
end
end
-#--------------------------------------------------------------------------
+#------------------------------------------------------------------------------
class Server
- attr_reader :host, :port, :status, :logger
+
+ private
+
+ def done
+ fail unless @connections.empty?
+ EM.stop if @em_thread && EM.reactor_running?
+ @connections, @status, @sig, @em_thread = [], :stopped, nil, nil
+ sleep 0.1 unless EM.reactor_thread? # give EM a chance to stop
+ logger.debug EM.reactor_running?? "server done but EM still running": "server really done"
+ end
+
+ def initialize_connection(conn)
+ logger.debug "starting connection"
+ fail unless EM.reactor_thread?
+ @connections << conn
+ conn.req_handler, conn.comm_inactivity_timeout = @req_handler.new(self), 30
+ end
+
+ public
+
+ attr_reader :host, :port, :status, :logger, :root
attr_accessor :info
def url; "http://#{@host}:#{@port}" end
def trace(msg = nil, &blk); logger.trace(msg, &blk) if logger.respond_to?(:trace) end
- def initialize(req_handler, logger = Logger.new($stdout), info = nil)
- @req_handler, @logger, @info = req_handler, logger, info
+ def initialize(req_handler, options)
+ @req_handler = req_handler
+ @logger = options[:logger] || Logger.new($stdout)
+ @info = options[:info]
+ @host = options[:host] || "localhost"
+ @init_port = options[:port] || 0
+ @root = options[:root]
@connections, @status, @sig, @em_thread = [], :stopped, nil, nil
end
- def start(hostname = "localhost", port = nil)
+ def start
raise ArgumentError, "attempt to start a server that's already running" unless @status == :stopped
- @host = hostname
logger.debug "starting #{self.class} server #{@host}"
EM.schedule do
- @sig = EM.start_server(@host, port || 0, Connection) { |c| initialize_connection(c) }
+ @sig = EM.start_server(@host, @init_port, Connection) { |c| initialize_connection(c) }
@port = Socket.unpack_sockaddr_in(EM.get_sockname(@sig))[0]
- logger.debug "#{self.class} server started at #{url}, signature #{@sig}"
+ logger.info "#{self.class} server started at #{url}"
end
@status = :running
self
end
- def run_on_thread(hostname = "localhost", port = 0)
+ def run_on_thread
raise ArgumentError, "can't run on thread, EventMachine already running" if EM.reactor_running?
logger.debug { "starting eventmachine on thread" }
cthred = Thread.current
@em_thread = Thread.new do
begin
- EM.run { start(hostname, port); cthred.run }
+ EM.run { start; cthred.run }
logger.debug "server thread done"
rescue Exception => e
logger.debug { "unhandled exception on stub server thread: #{e.message}" }
trace { e.backtrace }
raise
@@ -258,14 +283,14 @@
Thread.stop
logger.debug "running on thread"
self
end
- def run(hostname = "localhost", port = 0)
+ def run
raise ArgumentError, "can't run, EventMachine already running" if EM.reactor_running?
@em_thread = Thread.current
- EM.run { start(hostname, port) }
+ EM.run { start }
logger.debug "server and event machine done"
end
# if on reactor thread, start shutting down but return if connections still
# in process, and let them disconnect when complete -- server is not really
@@ -282,28 +307,9 @@
def delete_connection(conn)
logger.debug "deleting connection"
fail unless EM.reactor_thread?
@connections.delete(conn)
done if @status != :running && @connections.empty?
- end
-
- private
-
- def done
- fail unless @connections.empty?
- EM.stop if @em_thread && EM.reactor_running?
- @connections, @status, @sig, @em_thread = [], :stopped, nil, nil
- sleep 0.1 unless EM.reactor_thread? # give EM a chance to stop
- logger.debug EM.reactor_running? ?
- "server done but EM still running" : "server really done"
- end
-
- def initialize_connection(conn)
- logger.debug "starting connection"
- fail unless EM.reactor_thread?
- @connections << conn
- conn.req_handler = @req_handler.new(self)
- conn.comm_inactivity_timeout = 30
end
end
end