From 8aa40990d5850daa017845271be332c28d955c16 Mon Sep 17 00:00:00 2001 From: Sunrise Date: Fri, 3 May 2024 00:51:08 +0800 Subject: [PATCH 1/4] Support setting routes for serving static files --- src/grip/application.cr | 14 +++++++++----- src/grip/handlers/static.cr | 25 ++++++++++++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/grip/application.cr b/src/grip/application.cr index 3551f46..4944b25 100644 --- a/src/grip/application.cr +++ b/src/grip/application.cr @@ -11,7 +11,7 @@ module Grip getter exception_handler : Grip::Handlers::Exception getter pipeline_handler : Grip::Handlers::Pipeline getter websocket_handler : Grip::Routers::WebSocket - getter static_handler : Grip::Handlers::Static? + getter static_handler : Array(Grip::Handlers::Static) = [] of Grip::Handlers::Static property router : Array(HTTP::Handler) @@ -26,8 +26,8 @@ module Grip @pipeline_handler = Grip::Handlers::Pipeline.new(@http_handler, @websocket_handler) @exception_handler = Grip::Handlers::Exception.new(@environment) - if serve_static - @static_handler = Grip::Handlers::Static.new(pubilc_dir, fallthrough, directory_listing) + serve_static && static_routes.each do |route, path| + @static_handler << Grip::Handlers::Static.new(path, fallthrough, directory_listing, route) end @router = [ @@ -54,6 +54,10 @@ module Grip "./public" end + def static_routes : Hash(String, String) + {"/" => pubilc_dir} + end + def fallthrough : Bool false end @@ -63,8 +67,8 @@ module Grip end def server : HTTP::Server - if serve_static - @router.insert(1, @static_handler.not_nil!) + serve_static && @static_handler.each do |handler| + @router.insert(1, handler) end HTTP::Server.new(@router) diff --git a/src/grip/handlers/static.cr b/src/grip/handlers/static.cr index ee1f56c..c2cf007 100644 --- a/src/grip/handlers/static.cr +++ b/src/grip/handlers/static.cr @@ -8,14 +8,17 @@ module Grip module Handlers class Static < HTTP::StaticFileHandler - def initialize(public_dir : String, fallthrough = false, directory_listing = false) - super + def initialize(public_dir : String, @fallthrough = true, @directory_listing = true, @routing = "/") + @public_dir = Path.new(public_dir).expand end def call(context : HTTP::Server::Context) return allow_get_or_head(context) unless method_get_or_head?(context.request.method) + # 1. / -> ./public + # 2. /foo/bar -> ./public + # 3. /foo/bar/ -> ./public - original_path = context.request.path.not_nil! + original_path = context.request.path.not_nil! # / /foo/bar /foo/bar/ request_path = URI.decode(original_path) # File path cannot contain '\0' (NUL) because all filesystem I know @@ -28,20 +31,26 @@ module Grip is_dir_path = dir_path? original_path expanded_path = Path.posix(request_path).expand("/").to_s expanded_path += "/" if is_dir_path && !dir_path?(expanded_path) - is_dir_path = dir_path? expanded_path - file_path = File.join(@public_dir, expanded_path) - root_file = File.join(@public_dir, expanded_path, "index.html") + relative_path = request_path.lchop(routing) # "" "" / + + is_dir_path = dir_path? expanded_path # false false true + file_path = File.join([@public_dir] + relative_path.split("/")) # ./public ./public ./public + root_file = File.join([@public_dir] + relative_path.split("/") + ["index.html"]) # ./public/index.html ./public/index.html ./public/index.html if is_dir_path && File.exists? root_file return if etag(context, root_file) return context.send_file(root_file, gzip_enabled: self.class.config_gzip?(static_config)) end - is_dir_path = Dir.exists?(file_path) && !is_dir_path + is_dir_path = Dir.exists?(file_path) && !is_dir_path # true if request_path != expanded_path || is_dir_path redirect_to context, file_redirect_path(expanded_path, is_dir_path) end + # private def redirect_to(context, url) + # context.response.redirect url.to_s + # end + call_next_with_file_path(context, request_path, file_path) end @@ -103,6 +112,8 @@ module Grip def self.config_gzip?(config) config.is_a?(Hash) && config["gzip"] == true end + + getter routing : String end end end From d09b5d5094ff7e0e375362ab0f3a7a4fa83b84c2 Mon Sep 17 00:00:00 2001 From: Sunrise Date: Fri, 3 May 2024 00:57:29 +0800 Subject: [PATCH 2/4] Fix --- src/grip/handlers/static.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grip/handlers/static.cr b/src/grip/handlers/static.cr index c2cf007..fbd8d4b 100644 --- a/src/grip/handlers/static.cr +++ b/src/grip/handlers/static.cr @@ -8,7 +8,7 @@ module Grip module Handlers class Static < HTTP::StaticFileHandler - def initialize(public_dir : String, @fallthrough = true, @directory_listing = true, @routing = "/") + def initialize(public_dir : String, @fallthrough = false, @directory_listing = false, @routing = "/") @public_dir = Path.new(public_dir).expand end From d27ffa5bbd78d27e4cc9220138b7391de760b91e Mon Sep 17 00:00:00 2001 From: Sunrise Date: Sun, 5 May 2024 15:45:22 +0800 Subject: [PATCH 3/4] Use native path --- src/grip/handlers/static.cr | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/grip/handlers/static.cr b/src/grip/handlers/static.cr index fbd8d4b..87ed56d 100644 --- a/src/grip/handlers/static.cr +++ b/src/grip/handlers/static.cr @@ -14,11 +14,8 @@ module Grip def call(context : HTTP::Server::Context) return allow_get_or_head(context) unless method_get_or_head?(context.request.method) - # 1. / -> ./public - # 2. /foo/bar -> ./public - # 3. /foo/bar/ -> ./public - original_path = context.request.path.not_nil! # / /foo/bar /foo/bar/ + original_path = context.request.path.not_nil! request_path = URI.decode(original_path) # File path cannot contain '\0' (NUL) because all filesystem I know @@ -31,26 +28,22 @@ module Grip is_dir_path = dir_path? original_path expanded_path = Path.posix(request_path).expand("/").to_s expanded_path += "/" if is_dir_path && !dir_path?(expanded_path) - relative_path = request_path.lchop(routing) # "" "" / + relative_path = request_path.lchop(routing) - is_dir_path = dir_path? expanded_path # false false true - file_path = File.join([@public_dir] + relative_path.split("/")) # ./public ./public ./public - root_file = File.join([@public_dir] + relative_path.split("/") + ["index.html"]) # ./public/index.html ./public/index.html ./public/index.html + is_dir_path = dir_path? expanded_path + file_path = File.join(@public_dir, Path[relative_path]) + root_file = File.join(@public_dir, Path[relative_path], "index.html") if is_dir_path && File.exists? root_file return if etag(context, root_file) return context.send_file(root_file, gzip_enabled: self.class.config_gzip?(static_config)) end - is_dir_path = Dir.exists?(file_path) && !is_dir_path # true + is_dir_path = Dir.exists?(file_path) && !is_dir_path if request_path != expanded_path || is_dir_path redirect_to context, file_redirect_path(expanded_path, is_dir_path) end - # private def redirect_to(context, url) - # context.response.redirect url.to_s - # end - call_next_with_file_path(context, request_path, file_path) end From bf23ab5fdaa1c4b92d449b7ca54dfc168c2b2255 Mon Sep 17 00:00:00 2001 From: Sunrise Date: Sat, 11 May 2024 23:13:24 +0800 Subject: [PATCH 4/4] Fix unexpected static routing --- src/grip/handlers/static.cr | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/grip/handlers/static.cr b/src/grip/handlers/static.cr index 87ed56d..6cc5277 100644 --- a/src/grip/handlers/static.cr +++ b/src/grip/handlers/static.cr @@ -28,7 +28,10 @@ module Grip is_dir_path = dir_path? original_path expanded_path = Path.posix(request_path).expand("/").to_s expanded_path += "/" if is_dir_path && !dir_path?(expanded_path) - relative_path = request_path.lchop(routing) + relative_path = request_path.lchop?(routing) || begin + call_next(context) + expanded_path + end is_dir_path = dir_path? expanded_path file_path = File.join(@public_dir, Path[relative_path])