mirror of
				https://gitea.invidious.io/iv-org/shard-kemal.git
				synced 2024-08-15 00:53:36 +00:00 
			
		
		
		
	Add allocation optimizations (#487)
This commit is contained in:
		
							parent
							
								
									afd17fc774
								
							
						
					
					
						commit
						21ab64511a
					
				
					 12 changed files with 59 additions and 82 deletions
				
			
		
							
								
								
									
										13
									
								
								src/kemal.cr
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								src/kemal.cr
									
										
									
									
									
								
							|  | @ -68,15 +68,12 @@ module Kemal | |||
|   end | ||||
| 
 | ||||
|   def self.stop | ||||
|     if config.running | ||||
|       if server = config.server | ||||
|         server.close unless server.closed? | ||||
|         config.running = false | ||||
|       else | ||||
|         raise "Kemal.config.server is not set. Please use Kemal.run to set the server." | ||||
|       end | ||||
|     raise "Kemal is already stopped." if !config.running | ||||
|     if server = config.server | ||||
|       server.close unless server.closed? | ||||
|       config.running = false | ||||
|     else | ||||
|       raise "Kemal is already stopped." | ||||
|       raise "Kemal.config.server is not set. Please use Kemal.run to set the server." | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,14 +41,8 @@ module Kemal | |||
|     private def configure_ssl | ||||
|       {% if !flag?(:without_openssl) %} | ||||
|       if @ssl_enabled | ||||
|         unless @key_file | ||||
|           puts "SSL Key Not Found" | ||||
|           exit | ||||
|         end | ||||
|         unless @cert_file | ||||
|           puts "SSL Certificate Not Found" | ||||
|           exit | ||||
|         end | ||||
|         abort "SSL Key Not Found" if !@key_file | ||||
|         abort "SSL Certificate Not Found" if !@cert_file | ||||
|         ssl = Kemal::SSL.new | ||||
|         ssl.key_file = @key_file.not_nil! | ||||
|         ssl.cert_file =  @cert_file.not_nil! | ||||
|  | @ -58,7 +52,9 @@ module Kemal | |||
|     end | ||||
| 
 | ||||
|     private def read_env | ||||
|       @config.env = ENV["KEMAL_ENV"] if ENV.has_key?("KEMAL_ENV") | ||||
|       if kemal_env = ENV["KEMAL_ENV"]? | ||||
|         @config.env = kemal_env | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -144,15 +144,10 @@ module Kemal | |||
|     end | ||||
| 
 | ||||
|     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 | ||||
|       CUSTOM_HANDLERS.each do |ch0, ch1| | ||||
|         position = ch0 | ||||
|         HANDLERS.insert (position || @handler_position), ch1 | ||||
|         @handler_position += 1 | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ module Kemal | |||
|     def _add_route_filter(verb : String, path, type, &block : HTTP::Server::Context -> _) | ||||
|       lookup = lookup_filters_for_path_type(verb, path, type) | ||||
|       if lookup.found? && lookup.payload.is_a?(Array(FilterBlock)) | ||||
|         (lookup.payload.as(Array(FilterBlock))) << FilterBlock.new(&block) | ||||
|         lookup.payload << FilterBlock.new(&block) | ||||
|       else | ||||
|         @tree.add radix_path(verb, path, type), [FilterBlock.new(&block)] | ||||
|       end | ||||
|  | @ -54,8 +54,8 @@ module Kemal | |||
|     private def call_block_for_path_type(verb : String?, path : String, type, context : HTTP::Server::Context) | ||||
|       lookup = lookup_filters_for_path_type(verb, path, type) | ||||
|       if lookup.found? && lookup.payload.is_a? Array(FilterBlock) | ||||
|         blocks = lookup.payload.as(Array(FilterBlock)) | ||||
|         blocks.each { |block| block.call(context) } | ||||
|         blocks = lookup.payload | ||||
|         blocks.each &.call(context) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,15 +11,17 @@ module Kemal | |||
| 
 | ||||
|     macro only(paths, method = "GET") | ||||
|       class_name = {{@type.name}} | ||||
|       method_downcase = {{method}}.downcase | ||||
|       class_name_method = "#{class_name}/#{method_downcase}" | ||||
|       ({{paths}}).each do |path| | ||||
|         @@only_routes_tree.add "#{class_name}/#{{{method}}.downcase}#{path}", "/#{{{method}}.downcase}#{path}" | ||||
|         @@only_routes_tree.add class_name_method + path, '/' + method_downcase + path | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     macro exclude(paths, method = "GET") | ||||
|       class_name = {{@type.name}} | ||||
|       ({{paths}}).each do |path| | ||||
|         @@exclude_routes_tree.add "#{class_name}/#{{{method}}.downcase}#{path}", "/#{{{method}}.downcase}#{path}" | ||||
|         @@exclude_routes_tree.add class_name_method + path, '/' + method_downcase + path | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -127,12 +127,14 @@ def send_file(env : HTTP::Server::Context, path : String, mime_type : String? = | |||
|     if env.request.method == "GET" && env.request.headers.has_key?("Range") | ||||
|       next multipart(file, env) | ||||
|     end | ||||
|     if request_headers.includes_word?("Accept-Encoding", "gzip") && config.is_a?(Hash) && config["gzip"] == true && filesize > minsize && Kemal::Utils.zip_types(file_path) | ||||
| 
 | ||||
|     condition = config.is_a?(Hash) && config["gzip"]? == true && filesize > minsize && Kemal::Utils.zip_types(file_path) | ||||
|     if condition && request_headers.includes_word?("Accept-Encoding", "gzip") | ||||
|       env.response.headers["Content-Encoding"] = "gzip" | ||||
|       Gzip::Writer.open(env.response) do |deflate| | ||||
|         IO.copy(file, deflate) | ||||
|       end | ||||
|     elsif request_headers.includes_word?("Accept-Encoding", "deflate") && config.is_a?(Hash) && config["gzip"]? == true && filesize > minsize && Kemal::Utils.zip_types(file_path) | ||||
|     elsif condition && request_headers.includes_word?("Accept-Encoding", "deflate") | ||||
|       env.response.headers["Content-Encoding"] = "deflate" | ||||
|       Flate::Writer.open(env.response) do |deflate| | ||||
|         IO.copy(file, deflate) | ||||
|  | @ -148,28 +150,16 @@ end | |||
| private def multipart(file, env : HTTP::Server::Context) | ||||
|   # See http://httpwg.org/specs/rfc7233.html | ||||
|   fileb = file.size | ||||
|   startb = endb = 0 | ||||
| 
 | ||||
|   range = env.request.headers["Range"] | ||||
|   match = range.match(/bytes=(\d{1,})-(\d{0,})/) | ||||
| 
 | ||||
|   startb = 0 | ||||
|   endb = 0 | ||||
| 
 | ||||
|   if match | ||||
|     if match.size >= 2 | ||||
|       startb = match[1].to_i { 0 } | ||||
|     end | ||||
| 
 | ||||
|     if match.size >= 3 | ||||
|       endb = match[2].to_i { 0 } | ||||
|     end | ||||
|   if match = env.request.headers["Range"].match /bytes=(\d{1,})-(\d{0,})/ | ||||
|     startb = match[1].to_i { 0 } if match.size >= 2 | ||||
|     endb = match[2].to_i { 0 } if match.size >= 3 | ||||
|   end | ||||
| 
 | ||||
|   if endb == 0 | ||||
|     endb = fileb - 1 | ||||
|   end | ||||
|   endb = fileb - 1 if endb == 0 | ||||
| 
 | ||||
|   if startb < endb && endb < fileb | ||||
|   if startb < endb < fileb | ||||
|     content_length = 1 + endb - startb | ||||
|     env.response.status_code = 206 | ||||
|     env.response.content_length = content_length | ||||
|  | @ -179,12 +169,12 @@ private def multipart(file, env : HTTP::Server::Context) | |||
|     if startb > 1024 | ||||
|       skipped = 0 | ||||
|       # file.skip only accepts values less or equal to 1024 (buffer size, undocumented) | ||||
|       until skipped + 1024 > startb | ||||
|       until (increase_skipped = skipped + 1024) > startb | ||||
|         file.skip(1024) | ||||
|         skipped += 1024 | ||||
|         skipped = increase_skipped | ||||
|       end | ||||
|       if skipped - startb > 0 | ||||
|         file.skip(skipped - startb) | ||||
|       if (skipped_minus_startb = skipped - startb) > 0 | ||||
|         file.skip skipped_minus_startb | ||||
|       end | ||||
|     else | ||||
|       file.skip(startb) | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| module Kemal | ||||
|   module Utils | ||||
|     ZIP_TYPES = [".htm", ".html", ".txt", ".css", ".js", ".svg", ".json", ".xml", ".otf", ".ttf", ".woff", ".woff2"] | ||||
|     ZIP_TYPES = {".htm", ".html", ".txt", ".css", ".js", ".svg", ".json", ".xml", ".otf", ".ttf", ".woff", ".woff2"} | ||||
| 
 | ||||
|     def self.path_starts_with_slash?(path : String) | ||||
|       path.starts_with?("/") | ||||
|       path.starts_with? '/' | ||||
|     end | ||||
| 
 | ||||
|     def self.zip_types(path : String) # https://github.com/h5bp/server-configs-nginx/blob/master/nginx.conf | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ module Kemal | |||
|       time = Time.now | ||||
|       call_next(context) | ||||
|       elapsed_text = elapsed_text(Time.now - time) | ||||
|       @io << time << " " << context.response.status_code << " " << context.request.method << " " << context.request.resource << " " << elapsed_text << "\n" | ||||
|       @io << time << ' ' << context.response.status_code << ' ' << context.request.method << ' ' << context.request.resource << ' ' << elapsed_text << '\n' | ||||
|       context | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ module Kemal | |||
|     end | ||||
| 
 | ||||
|     private def unescape_url_param(value : String) | ||||
|       value.size == 0 ? value : URI.unescape(value) | ||||
|       value.empty? ? value : URI.unescape(value) | ||||
|     rescue | ||||
|       value | ||||
|     end | ||||
|  | @ -74,19 +74,11 @@ module Kemal | |||
|     end | ||||
| 
 | ||||
|     private def parse_part(part : IO?) | ||||
|       if part | ||||
|         HTTP::Params.parse(part.gets_to_end) | ||||
|       else | ||||
|         HTTP::Params.parse("") | ||||
|       end | ||||
|       HTTP::Params.parse(part ? part.gets_to_end : "") | ||||
|     end | ||||
| 
 | ||||
|     private def parse_part(part : String?) | ||||
|       if part | ||||
|         HTTP::Params.parse(part.to_s) | ||||
|       else | ||||
|         HTTP::Params.parse("") | ||||
|       end | ||||
|       HTTP::Params.parse part.to_s | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ module Kemal | |||
|     end | ||||
| 
 | ||||
|     private def radix_path(method, path) | ||||
|       "/#{method.downcase}#{path}" | ||||
|       '/' + method.downcase + path | ||||
|     end | ||||
| 
 | ||||
|     private def add_to_radix_tree(method, path, route) | ||||
|  |  | |||
|  | @ -7,7 +7,9 @@ module Kemal | |||
|     def call(context : HTTP::Server::Context) | ||||
|       return call_next(context) if context.request.path.not_nil! == "/" | ||||
| 
 | ||||
|       unless context.request.method == "GET" || context.request.method == "HEAD" | ||||
|       case context.request.method | ||||
|       when "GET", "HEAD" | ||||
|       else | ||||
|         if @fallthrough | ||||
|           call_next(context) | ||||
|         else | ||||
|  | @ -19,7 +21,6 @@ module Kemal | |||
| 
 | ||||
|       config = Kemal.config.serve_static | ||||
|       original_path = context.request.path.not_nil! | ||||
|       is_dir_path = original_path.ends_with? "/" | ||||
|       request_path = URI.unescape(original_path) | ||||
| 
 | ||||
|       # File path cannot contains '\0' (NUL) because all filesystem I know | ||||
|  | @ -30,16 +31,20 @@ module Kemal | |||
|       end | ||||
| 
 | ||||
|       expanded_path = File.expand_path(request_path, "/") | ||||
|       if is_dir_path && !expanded_path.ends_with? "/" | ||||
|         expanded_path = "#{expanded_path}/" | ||||
|       end | ||||
|       is_dir_path = expanded_path.ends_with? "/" | ||||
|       is_dir_path = if original_path.ends_with?('/') && !expanded_path.ends_with? '/' | ||||
|                       expanded_path = expanded_path + '/' | ||||
|                       true | ||||
|                     else | ||||
|                       expanded_path.ends_with? '/' | ||||
|                     end | ||||
| 
 | ||||
|       file_path = File.join(@public_dir, expanded_path) | ||||
|       is_dir = Dir.exists? file_path | ||||
| 
 | ||||
|       if request_path != expanded_path || is_dir && !is_dir_path | ||||
|         redirect_to context, "#{expanded_path}#{is_dir && !is_dir_path ? "/" : ""}" | ||||
|       if request_path != expanded_path | ||||
|         redirect_to context, expanded_path | ||||
|       elsif is_dir && !is_dir_path | ||||
|         redirect_to context, expanded_path + '/' | ||||
|       end | ||||
| 
 | ||||
|       if Dir.exists?(file_path) | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ module Kemal | |||
|     end | ||||
| 
 | ||||
|     def lookup_ws_route(path : String) | ||||
|       @routes.find "/ws#{path}" | ||||
|       @routes.find "/ws" + path | ||||
|     end | ||||
| 
 | ||||
|     def add_route(path : String, &handler : HTTP::WebSocket, HTTP::Server::Context -> Void) | ||||
|  | @ -30,12 +30,12 @@ module Kemal | |||
|     end | ||||
| 
 | ||||
|     private def radix_path(method, path) | ||||
|       "/#{method.downcase}#{path}" | ||||
|       '/' + method.downcase + path | ||||
|     end | ||||
| 
 | ||||
|     private def websocket_upgrade_request?(context) | ||||
|       return false unless upgrade = context.request.headers["Upgrade"]? | ||||
|       return false unless upgrade.compare("websocket", case_insensitive: true) == 0 | ||||
|       return unless upgrade = context.request.headers["Upgrade"]? | ||||
|       return unless upgrade.compare("websocket", case_insensitive: true) == 0 | ||||
| 
 | ||||
|       context.request.headers.includes_word?("Connection", "Upgrade") | ||||
|     end | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue