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