From 1d056b203b8a4551cab37fc8c975151a228e3c66 Mon Sep 17 00:00:00 2001 From: sdogruyol Date: Tue, 11 Jul 2017 11:22:35 +0300 Subject: [PATCH] Dynamically insert handlers. Fixes #376 --- spec/config_spec.cr | 1 + spec/handler_spec.cr | 4 +- spec/helpers_spec.cr | 3 +- spec/spec_helper.cr | 2 +- src/kemal/config.cr | 76 ++++++++++++++++++++++++++++------- src/kemal/helpers/helpers.cr | 6 ++- src/kemal/null_log_handler.cr | 1 + 7 files changed, 73 insertions(+), 20 deletions(-) diff --git a/spec/config_spec.cr b/spec/config_spec.cr index e5460a1..e395518 100644 --- a/spec/config_spec.cr +++ b/spec/config_spec.cr @@ -26,6 +26,7 @@ describe "Config" do it "adds a custom handler" do config = Kemal.config config.add_handler CustomTestHandler.new + Kemal.config.setup config.handlers.size.should eq(6) end diff --git a/spec/handler_spec.cr b/spec/handler_spec.cr index b9c4c17..fb0230d 100644 --- a/spec/handler_spec.cr +++ b/spec/handler_spec.cr @@ -112,9 +112,6 @@ describe "Handler" do "Post" end add_handler PostOnlyHandler.new - request = HTTP::Request.new("POST", "/only") - client_response = call_request_on_app(request) - client_response.body.should eq "OnlyPost" add_handler PostExcludeHandler.new request = HTTP::Request.new("POST", "/only") client_response = call_request_on_app(request) @@ -124,6 +121,7 @@ describe "Handler" do it "adds a handler at given position" do post_handler = PostOnlyHandler.new add_handler post_handler, 1 + Kemal.config.setup Kemal.config.handlers[1].should eq post_handler end diff --git a/spec/helpers_spec.cr b/spec/helpers_spec.cr index 75b18c1..6511bce 100644 --- a/spec/helpers_spec.cr +++ b/spec/helpers_spec.cr @@ -11,6 +11,7 @@ describe "Macros" do describe "#add_handler" do it "adds a custom handler" do add_handler CustomTestHandler.new + Kemal.config.setup Kemal.config.handlers.size.should eq 6 end end @@ -24,7 +25,6 @@ describe "Macros" do it "sets a custom logger" do config = Kemal::Config::INSTANCE logger CustomLogHandler.new - config.handlers[4].should be_a(CustomLogHandler) config.logger.should be_a(CustomLogHandler) end end @@ -119,6 +119,7 @@ describe "Macros" do describe "#gzip" do it "adds HTTP::CompressHandler to handlers" do gzip true + Kemal.config.setup Kemal.config.handlers[4].should be_a(HTTP::CompressHandler) end end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index bdd5790..6d2e291 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -64,6 +64,7 @@ def call_request_on_app(request) end def build_main_handler + Kemal.config.setup main_handler = Kemal.config.handlers.first current_handler = main_handler Kemal.config.handlers.each_with_index do |handler, index| @@ -76,7 +77,6 @@ end Spec.before_each do config = Kemal.config config.env = "development" - config.setup end Spec.after_each do diff --git a/src/kemal/config.cr b/src/kemal/config.cr index c71819f..43fa96c 100644 --- a/src/kemal/config.cr +++ b/src/kemal/config.cr @@ -5,9 +5,12 @@ module Kemal # Kemal.config # class Config - INSTANCE = Config.new - HANDLERS = [] of HTTP::Handler - ERROR_HANDLERS = {} of Int32 => HTTP::Server::Context, Exception -> String + INSTANCE = Config.new + HANDLERS = [] of HTTP::Handler + CUSTOM_HANDLERS = [] of Tuple(Nil | Int32, HTTP::Handler) + WEBSOCKET_HANDLERS = [] of HTTP::WebSocketHandler + FILTER_HANDLERS = [] of HTTP::Handler + ERROR_HANDLERS = {} of Int32 => HTTP::Server::Context, Exception -> String {% if flag?(:without_openssl) %} @ssl : Bool? {% else %} @@ -31,10 +34,10 @@ module Kemal @always_rescue = true @server = uninitialized HTTP::Server @router_included = false - @custom_handler_position = 4 @default_handlers_setup = false @running = false @shutdown_message = true + @handler_position = 0 end def logger @@ -51,9 +54,13 @@ module Kemal def clear @router_included = false - @custom_handler_position = 4 + @handler_position = 0 @default_handlers_setup = false HANDLERS.clear + CUSTOM_HANDLERS.clear + WEBSOCKET_HANDLERS.clear + FILTER_HANDLERS.clear + ERROR_HANDLERS.clear end def handlers @@ -65,14 +72,20 @@ module Kemal HANDLERS.replace(handlers) end - def add_handler(handler : HTTP::Handler | HTTP::WebSocketHandler, position = Kemal.config.custom_handler_position) - setup - HANDLERS.insert position, handler - @custom_handler_position = @custom_handler_position + 1 + def add_handler(handler : HTTP::Handler) + CUSTOM_HANDLERS << {nil, handler} + end + + def add_handler(handler : HTTP::Handler, position : Int32) + CUSTOM_HANDLERS << {position, handler} + end + + def add_handler(handler : HTTP::WebSocketHandler) + WEBSOCKET_HANDLERS << handler end def add_filter_handler(handler : HTTP::Handler) - HANDLERS.insert HANDLERS.size - 1, handler + FILTER_HANDLERS << handler end def error_handlers @@ -92,6 +105,9 @@ module Kemal setup_log_handler setup_error_handler setup_static_file_handler + setup_custom_handlers + setup_filter_handlers + setup_websocket_handlers @default_handlers_setup = true @router_included = true HANDLERS.insert(HANDLERS.size, Kemal::RouteHandler::INSTANCE) @@ -99,7 +115,8 @@ module Kemal end private def setup_init_handler - HANDLERS.insert(0, Kemal::InitHandler::INSTANCE) + HANDLERS.insert(@handler_position, Kemal::InitHandler::INSTANCE) + @handler_position += 1 end private def setup_log_handler @@ -108,18 +125,49 @@ module Kemal else Kemal::NullLogHandler.new end - HANDLERS.insert(1, @logger.not_nil!) + HANDLERS.insert(@handler_position, @logger.not_nil!) + @handler_position += 1 end private def setup_error_handler if @always_rescue @error_handler ||= Kemal::CommonExceptionHandler.new - HANDLERS.insert(2, @error_handler.not_nil!) + HANDLERS.insert(@handler_position, @error_handler.not_nil!) + @handler_position += 1 end end private def setup_static_file_handler - HANDLERS.insert(3, Kemal::StaticFileHandler.new(@public_folder)) if @serve_static.is_a?(Hash) + if @serve_static.is_a?(Hash) + HANDLERS.insert(@handler_position, Kemal::StaticFileHandler.new(@public_folder)) + @handler_position += 1 + end + end + + # Handle WebSocketHandler + private def setup_custom_handlers + CUSTOM_HANDLERS.each do |ch| + position = ch[0] + if !position + HANDLERS.insert(@handler_position, ch[1]) + @handler_position += 1 + else + HANDLERS.insert(position, ch[1]) + @handler_position += 1 + end + end + end + + private def setup_websocket_handlers + WEBSOCKET_HANDLERS.each do |h| + HANDLERS.insert(@handler_position, h) + end + end + + private def setup_filter_handlers + FILTER_HANDLERS.each do |h| + HANDLERS.insert(@handler_position, h) + end end end diff --git a/src/kemal/helpers/helpers.cr b/src/kemal/helpers/helpers.cr index b270c51..489ab27 100644 --- a/src/kemal/helpers/helpers.cr +++ b/src/kemal/helpers/helpers.cr @@ -8,7 +8,11 @@ # - Kemal::StaticFileHandler # - Here goes custom handlers # - Kemal::RouteHandler -def add_handler(handler, position = Kemal.config.custom_handler_position) +def add_handler(handler) + Kemal.config.add_handler handler +end + +def add_handler(handler, position : Int32) Kemal.config.add_handler handler, position end diff --git a/src/kemal/null_log_handler.cr b/src/kemal/null_log_handler.cr index e636465..c42173c 100644 --- a/src/kemal/null_log_handler.cr +++ b/src/kemal/null_log_handler.cr @@ -2,6 +2,7 @@ module Kemal # This is here to represent the logger corresponding to Null Object Pattern. class NullLogHandler < Kemal::BaseLogHandler def call(context) + puts "This is null" call_next(context) end