lib/jobim/server.rb in jobim-0.5.0 vs lib/jobim/server.rb in jobim-0.6.0

- old
+ new

@@ -1,45 +1,105 @@ +require 'thin' require 'rack' require 'rack/rewrite' -module Jobim::Server +# HTTP Server container. Contains the Rack application definition and routing +# tables. Class explicitly leverages `::Thin::Server` to create the HTTP +# server, this should possibly be changed. +class Jobim::Server + # Utitly wrapper to create and start a new `Jobim::Server` instnace. + # + # @param opts [Hash] option hash for server configuration + # @return [Jobim::Server] new running server instance + def self.start!(opts) + Jobim::Server.new(opts).start + end - def self.start(opts) - app = Rack::Builder.new do + attr_accessor :app, :settings, :server + + def initialize(settings, &block) + @settings = settings + + yield self if block_given? + end + + # Memoized accessor for the server Rack application. + # + # NB. This has been split into a memoized called to `#build_app` becuase of + # the way the `Rack::Builder` class handles scope in the context of + # `instance_eval` instead of `yield`. + # + # @return [Rack::Builder] + def app + @app ||= build_app(settings) + end + + # Memoized accessor for the internal server instance. + # + # This is currently explicitly a `::Thin::Server`, possibly should change + # into a more generic form. + # + # @return [Thin::Server] + def server + if @server.nil? + thin_app = Rack::Chunked.new(Rack::ContentLength.new(app)) + server = ::Thin::Server.new(settings.host, settings.port, thin_app) + + if settings.daemonize + server.pid_file = 'jobim.pid' + server.log_file = 'jobim.log' + end + + @server = server + end + + @server + end + + # Pass through delegation to the internal server object's start method. + # Handles daemonizing the server before starting it if nessesary. + def start + Thin::Logging.silent = settings.quiet + + puts ">>> Serving #{settings.dir}" + + server.daemonize if settings.daemonize + server.start + end + + private + + # Method to create a new instance of the Rack application. The creation + # functionality has been broken out into its own method for scope + # reason. `Rack::Builder` uses instance_eval which makes generating + # applicaitons a pain. + # + # @param opts [Hash] option hash for server configuration + # @return [Rack::Builder] Rack::Builder instance for application routing + def build_app(opts) + Rack::Builder.new do use Rack::Rewrite do - rewrite(%r{(.*)}, lambda do |match, env| - request_path = env["REQUEST_PATH"] + rewrite(/(.*)/, lambda do |match, env| + request_path = env['PATH_INFO'] - return match[1] if opts[:Prefix].length > request_path.length + return match[1] if opts.prefix.length > request_path.length - local_path = File.join(opts[:Dir], request_path[opts[:Prefix].length..-1]) + local_path = File.join(opts.dir, + request_path[opts.prefix.length..-1]) - if File.directory?(local_path) and - File.exists?(File.join(local_path, "index.html")) - File.join(request_path, "index.html") + if File.directory?(local_path) && + File.exists?(File.join(local_path, 'index.html')) + File.join(request_path, 'index.html') else match[1] end end) end use Rack::CommonLogger, STDOUT - map opts[:Prefix] do - run Rack::Directory.new(opts[:Dir]) + map opts.prefix do + run Rack::Directory.new(opts.dir) end end - - puts ">>> Serving #{opts[:Dir]}" - - Rack::Handler::Thin.run(app, opts) do |server| - if opts[:Daemonize] - server.pid_file = 'jobim.pid' - server.log_file = 'jobim.log' - server.daemonize - end - - Thin::Logging.silent = opts[:Quiet] - end end - end