diff options
author | Paul Duncan <pabs@pablotron.org> | 2016-07-16 22:17:12 -0400 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2016-07-16 22:17:12 -0400 |
commit | 0972589bc4fac2d673d122acf5866e2b7416ca25 (patch) | |
tree | 3f7696fc67047b0c0e95f0ce99e797aa519959a9 | |
parent | 1e7ed83cbd2ddd58e8e60a4384eab011e23c22a6 (diff) | |
download | guff-0972589bc4fac2d673d122acf5866e2b7416ca25.tar.bz2 guff-0972589bc4fac2d673d122acf5866e2b7416ca25.zip |
refactor etag and magic handling
-rw-r--r-- | src/guff/context.cr | 3 | ||||
-rw-r--r-- | src/guff/etag.cr | 14 | ||||
-rw-r--r-- | src/guff/handlers.cr | 61 |
3 files changed, 21 insertions, 57 deletions
diff --git a/src/guff/context.cr b/src/guff/context.cr index 7ab7b1e..6bb756e 100644 --- a/src/guff/context.cr +++ b/src/guff/context.cr @@ -1,8 +1,9 @@ class Guff::Context - getter :config, :dbs + getter :config, :dbs, :magic def initialize(@config : Config) @dbs = DatabasePair.new(@config.db_path, development?) + @magic = Magic.new end def models diff --git a/src/guff/etag.cr b/src/guff/etag.cr new file mode 100644 index 0000000..db24a88 --- /dev/null +++ b/src/guff/etag.cr @@ -0,0 +1,14 @@ +module Guff::ETag + def self.get_file_etag(path : String) + st = File.stat(path) + + # FIXME: rather than a hash this should be an HMAC + d = OpenSSL::Digest.new("SHA1") + + # FIXME: should this be inode rather than path? + d << "%s-%d-%d" % [path, st.size, st.mtime.epoch_ms] + + # return digest + d.hexdigest + end +end diff --git a/src/guff/handlers.cr b/src/guff/handlers.cr index 3ff58d0..a0cb335 100644 --- a/src/guff/handlers.cr +++ b/src/guff/handlers.cr @@ -140,11 +140,6 @@ module Guff::Handlers end class AssetsHandler < Handler - def initialize(context : Context) - super(context) - @etags = {} of String => String - end - def call(context : HTTP::Server::Context) req_path = context.request.path.not_nil! @@ -153,7 +148,7 @@ module Guff::Handlers # get expanded path to file if abs_path = expand_path(req_path) # get file digest - etag = get_file_etag(abs_path) + etag = ETag.get_file_etag(abs_path) # check for cache header if context.request.headers["if-none-match"]? == etag @@ -206,11 +201,6 @@ module Guff::Handlers # return path if file exists, or nil otherwise File.file?(r) ? r : nil end - - private def get_file_etag(path : String) : String - # FIXME: rather than a hash this should be an HMAC - @etags[path] ||= OpenSSL::Digest.new("SHA1").file(path).hexdigest - end end class AdminPageHandler < AuthenticatedHandler @@ -546,11 +536,6 @@ module Guff::Handlers # FIXME: this is very similar to AssetsHandler, so maybe combine them? class FilesHandler < Handler - def initialize(context : Context) - super(context) - @magic = Magic.new - end - def call(context : HTTP::Server::Context) req_path = context.request.path.not_nil! @@ -559,7 +544,7 @@ module Guff::Handlers # get expanded path to file if abs_path = expand_path(req_path) # get file digest - etag = get_file_etag(abs_path) + etag = ETag.get_file_etag(abs_path) # check for cache header if context.request.headers["if-none-match"]? == etag @@ -569,7 +554,7 @@ module Guff::Handlers # not cached, set code and send headers context.response.headers["x-frame-options"] = "SAMEORIGIN" context.response.status_code = 200 - context.response.content_type = get_mime_type(abs_path) + context.response.content_type = @context.magic.file(abs_path) context.response.content_length = File.size(abs_path) context.response.headers["etag"] = etag @@ -613,23 +598,6 @@ module Guff::Handlers # return path if file exists, or nil otherwise File.file?(r) ? r : nil end - - private def get_file_etag(path : String) : String - st = File.stat(path) - - # FIXME: rather than a hash this should be an HMAC - d = OpenSSL::Digest.new("SHA1") - - # FIXME: should this be inode rather than path? - d << "%s-%d-%d" % [path, st.size, st.mtime.epoch_ms] - - # return digest - d.hexdigest - end - - private def get_mime_type(path : String) : String - @magic.file(path) - end end # FIXME: this is very similar to FilesHandler and AssetsHandler, so @@ -637,7 +605,6 @@ module Guff::Handlers class FileAPIHandler < AuthenticatedHandler def initialize(context : Context) super(context, %w{admin editor}) - @magic = Magic.new end def authenticated_call(context : HTTP::Server::Context) @@ -648,7 +615,7 @@ module Guff::Handlers # get expanded path to file if abs_path = expand_path(req_path) # get file digest - etag = get_file_etag(abs_path) + etag = ETag.get_file_etag(abs_path) # check for cache header if context.request.headers["if-none-match"]? == etag @@ -658,7 +625,7 @@ module Guff::Handlers # not cached, set code and send headers context.response.headers["x-frame-options"] = "SAMEORIGIN" context.response.status_code = 200 - context.response.content_type = get_mime_type(abs_path) + context.response.content_type = @context.magic.file(abs_path) context.response.content_length = File.size(abs_path) context.response.headers["etag"] = etag context.response.headers["content-disposition"] = "attachment" @@ -702,26 +669,8 @@ module Guff::Handlers # return path if file exists, or nil otherwise File.file?(r) ? r : nil end - - private def get_file_etag(path : String) : String - st = File.stat(path) - - # FIXME: rather than a hash this should be an HMAC - d = OpenSSL::Digest.new("SHA1") - - # FIXME: should this be inode rather than path? - d << "%s-%d-%d" % [path, st.size, st.mtime.epoch_ms] - - # return digest - d.hexdigest - end - - private def get_mime_type(path : String) : String - @magic.file(path) - end end - HANDLERS = [{ :dev => true, :id => :stub, |