kemal/src/kemal/config.cr

183 lines
4.7 KiB
Crystal

module Kemal
# Kemal::Config stores all the configuration options for a Kemal application.
# It's a singleton and you can access it like.
#
# Kemal.config
#
class Config
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 %}
@ssl : OpenSSL::SSL::Context::Server?
{% end %}
property host_binding, ssl, port, env, public_folder, logging, running,
always_rescue, serve_static : (Bool | Hash(String, Bool)), server, extra_options,
shutdown_message
getter custom_handler_position
property static_headers : (HTTP::Server::Response, String, File::Stat -> Void)?
def initialize
@host_binding = "0.0.0.0"
@port = 3000
@env = "development"
@serve_static = {"dir_listing" => false, "gzip" => true}
@public_folder = "./public"
@logging = true
@logger = nil
@error_handler = nil
@always_rescue = true
@server = uninitialized HTTP::Server
@router_included = false
@default_handlers_setup = false
@running = false
@shutdown_message = true
@handler_position = 0
end
def logger
@logger.not_nil!
end
def logger=(logger : Kemal::BaseLogHandler)
@logger = logger
end
def scheme
ssl ? "https" : "http"
end
def clear
@router_included = false
@handler_position = 0
@default_handlers_setup = false
HANDLERS.clear
CUSTOM_HANDLERS.clear
WEBSOCKET_HANDLERS.clear
FILTER_HANDLERS.clear
ERROR_HANDLERS.clear
end
def handlers
HANDLERS
end
def handlers=(handlers : Array(HTTP::Handler))
clear
HANDLERS.replace(handlers)
end
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)
FILTER_HANDLERS << handler
end
def error_handlers
ERROR_HANDLERS
end
def add_error_handler(status_code, &handler : HTTP::Server::Context, Exception -> _)
ERROR_HANDLERS[status_code] = ->(context : HTTP::Server::Context, error : Exception) { handler.call(context, error).to_s }
end
def extra_options(&@extra_options : OptionParser ->)
end
def setup
unless @default_handlers_setup && @router_included
setup_init_handler
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)
end
end
private def setup_init_handler
HANDLERS.insert(@handler_position, Kemal::InitHandler::INSTANCE)
@handler_position += 1
end
private def setup_log_handler
@logger ||= if @logging
Kemal::CommonLogHandler.new
else
Kemal::NullLogHandler.new
end
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(@handler_position, @error_handler.not_nil!)
@handler_position += 1
end
end
private def setup_static_file_handler
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
def self.config
yield Config::INSTANCE
end
def self.config
Config::INSTANCE
end
end