mirror of
				https://gitea.invidious.io/iv-org/shard-kemal.git
				synced 2024-08-15 00:53:36 +00:00 
			
		
		
		
	Middleware ordering (#236)
Improve and correct request middleware Request -> Middleware -> Filter -> Route
This commit is contained in:
		
							parent
							
								
									1b27f5c011
								
							
						
					
					
						commit
						922d6de4d1
					
				
					 6 changed files with 79 additions and 24 deletions
				
			
		
							
								
								
									
										30
									
								
								spec/handler_spec.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								spec/handler_spec.cr
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | require "./spec_helper" | ||||||
|  | 
 | ||||||
|  | class CustomTestHandler < HTTP::Handler | ||||||
|  |   def call(env) | ||||||
|  |     env.response << "Kemal" | ||||||
|  |     call_next env | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | describe "Handler" do | ||||||
|  |   it "adds custom handler before before_*" do | ||||||
|  |     filter_middleware = Kemal::Middleware::Filter.new | ||||||
|  |     filter_middleware._add_route_filter("GET", "/", :before) do |env| | ||||||
|  |       env.response << " is" | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     filter_middleware._add_route_filter("GET", "/", :before) do |env| | ||||||
|  |       env.response << " so" | ||||||
|  |     end | ||||||
|  |     add_handler CustomTestHandler.new | ||||||
|  | 
 | ||||||
|  |     get "/" do |env| | ||||||
|  |       " Great" | ||||||
|  |     end | ||||||
|  |     request = HTTP::Request.new("GET", "/") | ||||||
|  |     client_response = call_request_on_app(request) | ||||||
|  |     client_response.status_code.should eq(200) | ||||||
|  |     client_response.body.should eq("Kemal is so Great") | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -30,7 +30,7 @@ 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.last.should be_a(CustomLogHandler) |       config.handlers[4].should be_a(CustomLogHandler) | ||||||
|       config.logger.should be_a(CustomLogHandler) |       config.logger.should be_a(CustomLogHandler) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  | @ -77,7 +77,6 @@ describe "Macros" do | ||||||
|           "Content-Type"                => "text/plain", |           "Content-Type"                => "text/plain", | ||||||
|         } |         } | ||||||
|       end |       end | ||||||
| 
 |  | ||||||
|       request = HTTP::Request.new("GET", "/headers") |       request = HTTP::Request.new("GET", "/headers") | ||||||
|       response = call_request_on_app(request) |       response = call_request_on_app(request) | ||||||
|       response.headers["Access-Control-Allow-Origin"].should eq("*") |       response.headers["Access-Control-Allow-Origin"].should eq("*") | ||||||
|  | @ -126,11 +125,7 @@ describe "Macros" do | ||||||
|   describe "#gzip" do |   describe "#gzip" do | ||||||
|     it "adds HTTP::DeflateHandler to handlers" do |     it "adds HTTP::DeflateHandler to handlers" do | ||||||
|       gzip true |       gzip true | ||||||
|       Kemal.config.handlers.last.is_a?(HTTP::DeflateHandler).should eq true |       Kemal.config.handlers[4].should be_a(HTTP::DeflateHandler) | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     it "doesn't add HTTP::DeflateHandler to handlers by default" do |  | ||||||
|       Kemal.config.handlers.last.is_a?(HTTP::DeflateHandler).should eq false |  | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,14 +3,9 @@ require "../src/*" | ||||||
| 
 | 
 | ||||||
| include Kemal | include Kemal | ||||||
| 
 | 
 | ||||||
| class CustomTestHandler < HTTP::Handler |  | ||||||
|   def call(request) |  | ||||||
|     call_next request |  | ||||||
|   end |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| class CustomLogHandler < Kemal::BaseLogHandler | class CustomLogHandler < Kemal::BaseLogHandler | ||||||
|   def call(context) |   def call(env) | ||||||
|  |     call_next env | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def write(message) |   def write(message) | ||||||
|  | @ -44,20 +39,30 @@ def call_request_on_app(request) | ||||||
|   io = MemoryIO.new |   io = MemoryIO.new | ||||||
|   response = HTTP::Server::Response.new(io) |   response = HTTP::Server::Response.new(io) | ||||||
|   context = HTTP::Server::Context.new(request, response) |   context = HTTP::Server::Context.new(request, response) | ||||||
|   Kemal::RouteHandler::INSTANCE.call(context) |   main_handler = build_main_handler | ||||||
|  |   main_handler.call context | ||||||
|   response.close |   response.close | ||||||
|   io.rewind |   io.rewind | ||||||
|   HTTP::Client::Response.from_io(io, decompress: false) |   HTTP::Client::Response.from_io(io, decompress: false) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
|  | def build_main_handler | ||||||
|  |   main_handler = Kemal.config.handlers.first | ||||||
|  |   current_handler = main_handler | ||||||
|  |   Kemal.config.handlers.each_with_index do |handler, index| | ||||||
|  |     current_handler.next = handler | ||||||
|  |     current_handler = handler | ||||||
|  |   end | ||||||
|  |   main_handler | ||||||
|  | end | ||||||
|  | 
 | ||||||
| Spec.before_each do | Spec.before_each do | ||||||
|   config = Kemal.config |   config = Kemal.config | ||||||
|   config.env = "development" |   config.env = "development" | ||||||
|   config.setup |   config.setup | ||||||
|   config.add_handler Kemal::RouteHandler::INSTANCE |  | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| Spec.after_each do | Spec.after_each do | ||||||
|   Kemal.config.handlers.clear |   Kemal.config.clear | ||||||
|   Kemal::RouteHandler::INSTANCE.tree = Radix::Tree(Route).new |   Kemal::RouteHandler::INSTANCE.tree = Radix::Tree(Route).new | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -29,6 +29,9 @@ module Kemal | ||||||
|       @error_handler = nil |       @error_handler = nil | ||||||
|       @always_rescue = true |       @always_rescue = true | ||||||
|       @server = uninitialized HTTP::Server |       @server = uninitialized HTTP::Server | ||||||
|  |       @router_included = false | ||||||
|  |       @custom_handler_position = 4 | ||||||
|  |       @default_handlers_setup = false | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def logger |     def logger | ||||||
|  | @ -43,15 +46,30 @@ module Kemal | ||||||
|       ssl ? "https" : "http" |       ssl ? "https" : "http" | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     def clear | ||||||
|  |       @router_included = false | ||||||
|  |       @custom_handler_position = 4 | ||||||
|  |       @default_handlers_setup = false | ||||||
|  |       HANDLERS.clear | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     def handlers |     def handlers | ||||||
|       HANDLERS |       HANDLERS | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def add_handler(handler : HTTP::Handler) |     def add_handler(handler : HTTP::Handler) | ||||||
|       HANDLERS << handler |       setup | ||||||
|  |       HANDLERS.insert @custom_handler_position, handler | ||||||
|  |       @custom_handler_position = @custom_handler_position + 1 | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def add_filter_handler(handler : HTTP::Handler) | ||||||
|  |       setup | ||||||
|  |       HANDLERS.insert HANDLERS.size - 1, handler | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def add_ws_handler(handler : HTTP::WebSocketHandler) |     def add_ws_handler(handler : HTTP::WebSocketHandler) | ||||||
|  |       setup | ||||||
|       HANDLERS << handler |       HANDLERS << handler | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  | @ -67,10 +85,15 @@ module Kemal | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def setup |     def setup | ||||||
|       setup_init_handler |       unless @default_handlers_setup && @router_included | ||||||
|       setup_log_handler |         setup_init_handler | ||||||
|       setup_error_handler |         setup_log_handler | ||||||
|       setup_static_file_handler |         setup_error_handler | ||||||
|  |         setup_static_file_handler | ||||||
|  |         @default_handlers_setup = true | ||||||
|  |         @router_included = true | ||||||
|  |         HANDLERS.insert(HANDLERS.size, Kemal::RouteHandler::INSTANCE) | ||||||
|  |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     private def setup_init_handler |     private def setup_init_handler | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ module Kemal::Middleware | ||||||
|     # This middleware is lazily instantiated and added to the handlers as soon as a call to `after_X` or `before_X` is made. |     # This middleware is lazily instantiated and added to the handlers as soon as a call to `after_X` or `before_X` is made. | ||||||
|     def initialize |     def initialize | ||||||
|       @tree = Radix::Tree(Array(Kemal::Middleware::Block)).new |       @tree = Radix::Tree(Array(Kemal::Middleware::Block)).new | ||||||
|       Kemal.config.add_handler(self) |       Kemal.config.add_filter_handler(self) | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     # The call order of the filters is before_all -> before_x -> X -> after_x -> after_all |     # The call order of the filters is before_all -> before_x -> X -> after_x -> after_all | ||||||
|  |  | ||||||
|  | @ -8,7 +8,9 @@ module Kemal | ||||||
|     @method : String |     @method : String | ||||||
| 
 | 
 | ||||||
|     def initialize(@method, @path : String, &handler : HTTP::Server::Context -> _) |     def initialize(@method, @path : String, &handler : HTTP::Server::Context -> _) | ||||||
|       @handler = ->(context : HTTP::Server::Context) { handler.call(context).to_s } |       @handler = ->(context : HTTP::Server::Context) do | ||||||
|  |         handler.call(context).to_s | ||||||
|  |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue