Dynamically insert handlers. Fixes #376

This commit is contained in:
sdogruyol 2017-07-11 11:22:35 +03:00
parent dbbe05a610
commit 1d056b203b
7 changed files with 73 additions and 20 deletions

View file

@ -26,6 +26,7 @@ describe "Config" do
it "adds a custom handler" do it "adds a custom handler" do
config = Kemal.config config = Kemal.config
config.add_handler CustomTestHandler.new config.add_handler CustomTestHandler.new
Kemal.config.setup
config.handlers.size.should eq(6) config.handlers.size.should eq(6)
end end

View file

@ -112,9 +112,6 @@ describe "Handler" do
"Post" "Post"
end end
add_handler PostOnlyHandler.new 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 add_handler PostExcludeHandler.new
request = HTTP::Request.new("POST", "/only") request = HTTP::Request.new("POST", "/only")
client_response = call_request_on_app(request) client_response = call_request_on_app(request)
@ -124,6 +121,7 @@ describe "Handler" do
it "adds a handler at given position" do it "adds a handler at given position" do
post_handler = PostOnlyHandler.new post_handler = PostOnlyHandler.new
add_handler post_handler, 1 add_handler post_handler, 1
Kemal.config.setup
Kemal.config.handlers[1].should eq post_handler Kemal.config.handlers[1].should eq post_handler
end end

View file

@ -11,6 +11,7 @@ describe "Macros" do
describe "#add_handler" do describe "#add_handler" do
it "adds a custom handler" do it "adds a custom handler" do
add_handler CustomTestHandler.new add_handler CustomTestHandler.new
Kemal.config.setup
Kemal.config.handlers.size.should eq 6 Kemal.config.handlers.size.should eq 6
end end
end end
@ -24,7 +25,6 @@ describe "Macros" do
it "sets a custom logger" do it "sets a custom logger" do
config = Kemal::Config::INSTANCE config = Kemal::Config::INSTANCE
logger CustomLogHandler.new logger CustomLogHandler.new
config.handlers[4].should be_a(CustomLogHandler)
config.logger.should be_a(CustomLogHandler) config.logger.should be_a(CustomLogHandler)
end end
end end
@ -119,6 +119,7 @@ describe "Macros" do
describe "#gzip" do describe "#gzip" do
it "adds HTTP::CompressHandler to handlers" do it "adds HTTP::CompressHandler to handlers" do
gzip true gzip true
Kemal.config.setup
Kemal.config.handlers[4].should be_a(HTTP::CompressHandler) Kemal.config.handlers[4].should be_a(HTTP::CompressHandler)
end end
end end

View file

@ -64,6 +64,7 @@ def call_request_on_app(request)
end end
def build_main_handler def build_main_handler
Kemal.config.setup
main_handler = Kemal.config.handlers.first main_handler = Kemal.config.handlers.first
current_handler = main_handler current_handler = main_handler
Kemal.config.handlers.each_with_index do |handler, index| Kemal.config.handlers.each_with_index do |handler, index|
@ -76,7 +77,6 @@ end
Spec.before_each do Spec.before_each do
config = Kemal.config config = Kemal.config
config.env = "development" config.env = "development"
config.setup
end end
Spec.after_each do Spec.after_each do

View file

@ -5,9 +5,12 @@ module Kemal
# Kemal.config # Kemal.config
# #
class Config class Config
INSTANCE = Config.new INSTANCE = Config.new
HANDLERS = [] of HTTP::Handler HANDLERS = [] of HTTP::Handler
ERROR_HANDLERS = {} of Int32 => HTTP::Server::Context, Exception -> String 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) %} {% if flag?(:without_openssl) %}
@ssl : Bool? @ssl : Bool?
{% else %} {% else %}
@ -31,10 +34,10 @@ module Kemal
@always_rescue = true @always_rescue = true
@server = uninitialized HTTP::Server @server = uninitialized HTTP::Server
@router_included = false @router_included = false
@custom_handler_position = 4
@default_handlers_setup = false @default_handlers_setup = false
@running = false @running = false
@shutdown_message = true @shutdown_message = true
@handler_position = 0
end end
def logger def logger
@ -51,9 +54,13 @@ module Kemal
def clear def clear
@router_included = false @router_included = false
@custom_handler_position = 4 @handler_position = 0
@default_handlers_setup = false @default_handlers_setup = false
HANDLERS.clear HANDLERS.clear
CUSTOM_HANDLERS.clear
WEBSOCKET_HANDLERS.clear
FILTER_HANDLERS.clear
ERROR_HANDLERS.clear
end end
def handlers def handlers
@ -65,14 +72,20 @@ module Kemal
HANDLERS.replace(handlers) HANDLERS.replace(handlers)
end end
def add_handler(handler : HTTP::Handler | HTTP::WebSocketHandler, position = Kemal.config.custom_handler_position) def add_handler(handler : HTTP::Handler)
setup CUSTOM_HANDLERS << {nil, handler}
HANDLERS.insert position, handler end
@custom_handler_position = @custom_handler_position + 1
def add_handler(handler : HTTP::Handler, position : Int32)
CUSTOM_HANDLERS << {position, handler}
end
def add_handler(handler : HTTP::WebSocketHandler)
WEBSOCKET_HANDLERS << handler
end end
def add_filter_handler(handler : HTTP::Handler) def add_filter_handler(handler : HTTP::Handler)
HANDLERS.insert HANDLERS.size - 1, handler FILTER_HANDLERS << handler
end end
def error_handlers def error_handlers
@ -92,6 +105,9 @@ module Kemal
setup_log_handler setup_log_handler
setup_error_handler setup_error_handler
setup_static_file_handler setup_static_file_handler
setup_custom_handlers
setup_filter_handlers
setup_websocket_handlers
@default_handlers_setup = true @default_handlers_setup = true
@router_included = true @router_included = true
HANDLERS.insert(HANDLERS.size, Kemal::RouteHandler::INSTANCE) HANDLERS.insert(HANDLERS.size, Kemal::RouteHandler::INSTANCE)
@ -99,7 +115,8 @@ module Kemal
end end
private def setup_init_handler private def setup_init_handler
HANDLERS.insert(0, Kemal::InitHandler::INSTANCE) HANDLERS.insert(@handler_position, Kemal::InitHandler::INSTANCE)
@handler_position += 1
end end
private def setup_log_handler private def setup_log_handler
@ -108,18 +125,49 @@ module Kemal
else else
Kemal::NullLogHandler.new Kemal::NullLogHandler.new
end end
HANDLERS.insert(1, @logger.not_nil!) HANDLERS.insert(@handler_position, @logger.not_nil!)
@handler_position += 1
end end
private def setup_error_handler private def setup_error_handler
if @always_rescue if @always_rescue
@error_handler ||= Kemal::CommonExceptionHandler.new @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
end end
private def setup_static_file_handler 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
end end

View file

@ -8,7 +8,11 @@
# - Kemal::StaticFileHandler # - Kemal::StaticFileHandler
# - Here goes custom handlers # - Here goes custom handlers
# - Kemal::RouteHandler # - 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 Kemal.config.add_handler handler, position
end end

View file

@ -2,6 +2,7 @@ module Kemal
# This is here to represent the logger corresponding to Null Object Pattern. # This is here to represent the logger corresponding to Null Object Pattern.
class NullLogHandler < Kemal::BaseLogHandler class NullLogHandler < Kemal::BaseLogHandler
def call(context) def call(context)
puts "This is null"
call_next(context) call_next(context)
end end