aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2016-07-16 22:17:12 -0400
committerPaul Duncan <pabs@pablotron.org>2016-07-16 22:17:12 -0400
commit0972589bc4fac2d673d122acf5866e2b7416ca25 (patch)
tree3f7696fc67047b0c0e95f0ce99e797aa519959a9
parent1e7ed83cbd2ddd58e8e60a4384eab011e23c22a6 (diff)
downloadguff-0972589bc4fac2d673d122acf5866e2b7416ca25.tar.bz2
guff-0972589bc4fac2d673d122acf5866e2b7416ca25.zip
refactor etag and magic handling
-rw-r--r--src/guff/context.cr3
-rw-r--r--src/guff/etag.cr14
-rw-r--r--src/guff/handlers.cr61
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,