lib/angelo/server.rb in angelo-0.1.1 vs lib/angelo/server.rb in angelo-0.1.2
- old
+ new
@@ -1,5 +1,7 @@
+require 'openssl'
+
module Angelo
class Server < Reel::Server
include Celluloid::Logger
@@ -12,17 +14,25 @@
def on_connection connection
# RubyProf.resume
connection.each_request do |request|
meth = request.websocket? ? :socket : request.method.downcase.to_sym
- route! meth, connection, request
+ dispatch! meth, connection, request
end
# RubyProf.pause
end
private
+ def dispatch! meth, connection, request
+ if staticable?(meth) and lp = local_path(request.path)
+ static! meth, connection, request, lp
+ else
+ route! meth, connection, request
+ end
+ end
+
def route! meth, connection, request
rs = @base.routes[meth][request.path]
if rs
responder = rs.dup
responder.base = @base.new
@@ -30,9 +40,57 @@
responder.request = request
else
Angelo.log connection, request, nil, :not_found
connection.respond :not_found, DEFAULT_RESPONSE_HEADERS, NOT_FOUND
end
+ end
+
+ def local_path path
+ if @base.public_dir
+ lp = File.join(@base.public_dir, path)
+ File.file?(lp) ? lp : nil
+ end
+ end
+
+ def staticable? meth
+ STATICABLE.include? meth
+ end
+
+ def static! meth, connection, request, local_path
+ etag = etag_for local_path
+ if request.headers[IF_NONE_MATCH_HEADER_KEY] == etag
+ Angelo.log 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-Disposition
+ #
+ CONTENT_DISPOSITION_HEADER_KEY =>
+ DEFAULT_CONTENT_DISPOSITION + "; filename=#{File.basename local_path}",
+
+ # Content-Length
+ #
+ CONTENT_LENGTH_HEADER_KEY => File.size(local_path),
+
+ # ETag
+ #
+ ETAG_HEADER_KEY => etag
+
+ }
+ Angelo.log connection, request, nil, :ok, headers[CONTENT_LENGTH_HEADER_KEY]
+ connection.respond :ok, headers, (meth == :head ? nil : File.read(local_path))
+ end
+ end
+
+ 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
end
end