lib/slinky/server.rb in slinky-0.2.1 vs lib/slinky/server.rb in slinky-0.4.0

- old
+ new

@@ -1,123 +1,72 @@ module Slinky - CONTENT_TYPES = { - 'html' => 'text/html', - 'js' => 'application/x-javascript', - 'css' => 'text/css' - } - - EXTENSION_REGEX = /(.+)\.(\w+)/ - - class Server < EventMachine::Connection + module Server include EM::HttpServer - @compilers = [] - @compilers_by_ext = {} + # Sets the root directory from which files should be served + def self.dir= _dir; @dir = _dir; end + # Gets the root directory from which files should be served + def self.dir; @dir || "."; end - @files = {} - - class << self - def register_compiler klass, options - options[:klass] = klass - @compilers << options - options[:outputs].each do |output| - @compilers_by_ext[output] ||= [] - @compilers_by_ext[output] << options - end - end - - def compilers_by_ext - @compilers_by_ext - end + # Splits a uri into its components, returning only the path sans + # initial forward slash. + def self.path_for_uri uri + _, _, _, _, _, path, _, _ = URI.split uri + path[1..-1] #get rid of the leading / end - def files - self.class.instance_variable_get(:@files) - end - - def process_http_request - @resp = EventMachine::DelegatedHttpResponse.new(self) - - _, _, _, _, _, path, _, query = URI.split @http_request_uri - path = path[1..-1] #get rid of the leading / - _, file, extension = path.match(EXTENSION_REGEX).to_a - - compilers = self.class.compilers_by_ext - - # Check if we've already seen this file. If so, we can skip a - # bunch of processing. - if files[path] - serve_compiled_file files[path] - return - end - - # if there's a file extension and we have a compiler that - # outputs that kind of file, look for an input with the same - # name and an extension in our list - if extension && extension != "" && compilers[extension] - files_by_ext = {} - # find possible source files - Dir.glob("#{file}.*").each do |f| - _, _, ext = f.match(EXTENSION_REGEX).to_a - files_by_ext[ext] = f - end - - cfile = nil - # find a compiler that outputs the request kind of file and - # which has an input file type that exists on the file system - compilers[extension].each do |c| - c[:inputs].each do |i| - if files_by_ext[i] - cfile = CompiledFile.new files_by_ext[i], c[:klass], extension - files[path] = cfile - break - end - end - break if cfile - end - - if cfile - serve_compiled_file cfile + # Takes a manifest file and produces a response for it + def self.handle_file resp, mf + if mf + if path = mf.process + serve_file resp, path.to_s else - serve_file path + resp.status = 500 + resp.content = "Error compiling #{mf.source}" end else - serve_file path + not_found resp end + resp end - def serve_compiled_file cfile - cfile.file do |path, status, stdout, stderr| - if path - serve_file path - else - puts "Status: #{status.inspect}" - @resp.status = 500 - @resp.content = "Error compiling #{cfile.source}:\n #{stdout}" - @resp.send_response - end - end - end - - def serve_file path - if File.exists?(path) && size = File.size?(path) + # Serves a file from the file system + def self.serve_file resp, path + if File.exists?(path) && !File.directory?(path) + size = File.size(path) _, _, extension = path.match(EXTENSION_REGEX).to_a - @resp.content_type CONTENT_TYPES[extension] + resp.content_type MIME::Types.type_for(path).first # File reading code from rack/file.rb File.open path do |file| - @resp.content = "" + resp.content = "" while size > 0 part = file.read([8192, size].min) break unless part size -= part.length - @resp.content << part + resp.content << part end end - @resp.send_response else - @resp.status = 404 - @resp.content = "File '#{path}' not found." - @resp.send_response + not_found resp end + end + + # Returns the proper responce for files that do not exist + def self.not_found resp + resp.status = 404 + resp.content = "File not found" + end + + # Method called for every HTTP request made + def process_http_request + @manifest = Manifest.new(Server.dir) + + path = Server.path_for_uri(@http_request_uri) + file = @manifest.find_by_path(path) + resp = EventMachine::DelegatedHttpResponse.new(self) + if file.is_a? ManifestDir + file = @manifest.find_by_path(path+"/index.html") + end + Server.handle_file(resp, file).send_response end end end