diff options
author | schneems <richard.schneeman@gmail.com> | 2014-10-01 18:09:37 -0500 |
---|---|---|
committer | schneems <richard.schneeman@gmail.com> | 2014-10-02 07:42:20 -0500 |
commit | dc53a8c26dc55d21240233b3d83d36efdef6e924 (patch) | |
tree | 991037ede0df148b5aef7137f321591401f98d53 | |
parent | a71be3c914c10d1089238f4e21b029b885be4029 (diff) | |
download | rack-dc53a8c26dc55d21240233b3d83d36efdef6e924.tar.gz |
Less allocated objects on each request
How many? Using `memory_profiler` and a Rails app (codetriage.com), master uses: ``` rack/lib x 7318 ``` After this patch, the app uses: ``` rack/lib x 4598 ``` Or `(7318 - 4598) / 7318.0 * 100 # => 37.16` % fewer objects __PER REQUEST__. To do this, I extracted really commonly used strings into top level Rack constants. It makes for a bit of a big diff, but I believe the changes are worth it. Running benchmark/ips against the same app, I'm seeing a performance host of `2~4%` across the entire app response. This doesn't just make Rack faster, it will make your app faster. While we could certainly go overboard and pre-define ALL strings as constants, that would be pretty gnarly to work with. This patch goes after the largest of the low hanging fruit.
36 files changed, 129 insertions, 109 deletions
diff --git a/lib/rack.rb b/lib/rack.rb index 341514c5..97817bcb 100644 --- a/lib/rack.rb +++ b/lib/rack.rb @@ -22,6 +22,16 @@ module Rack def self.release "1.5" end + PATH_INFO = 'PATH_INFO'.freeze + REQUEST_METHOD = 'REQUEST_METHOD'.freeze + SCRIPT_NAME = 'SCRIPT_NAME'.freeze + QUERY_STRING = 'QUERY_STRING'.freeze + CACHE_CONTROL = 'Cache-Control'.freeze + CONTENT_LENGTH = 'Content-Length'.freeze + CONTENT_TYPE = 'Content-Type'.freeze + + GET = 'GET'.freeze + HEAD = 'HEAD'.freeze autoload :Builder, "rack/builder" autoload :BodyProxy, "rack/body_proxy" diff --git a/lib/rack/auth/abstract/handler.rb b/lib/rack/auth/abstract/handler.rb index 214df629..c657691e 100644 --- a/lib/rack/auth/abstract/handler.rb +++ b/lib/rack/auth/abstract/handler.rb @@ -17,8 +17,8 @@ module Rack def unauthorized(www_authenticate = challenge) return [ 401, - { 'Content-Type' => 'text/plain', - 'Content-Length' => '0', + { CONTENT_TYPE => 'text/plain', + CONTENT_LENGTH => '0', 'WWW-Authenticate' => www_authenticate.to_s }, [] ] @@ -26,8 +26,8 @@ module Rack def bad_request return [ 400, - { 'Content-Type' => 'text/plain', - 'Content-Length' => '0' }, + { CONTENT_TYPE => 'text/plain', + CONTENT_LENGTH => '0' }, [] ] end diff --git a/lib/rack/auth/digest/request.rb b/lib/rack/auth/digest/request.rb index 706c651c..01994364 100644 --- a/lib/rack/auth/digest/request.rb +++ b/lib/rack/auth/digest/request.rb @@ -7,7 +7,7 @@ module Rack module Digest class Request < Auth::AbstractRequest def method - @env['rack.methodoverride.original_method'] || @env['REQUEST_METHOD'] + @env['rack.methodoverride.original_method'] || @env[REQUEST_METHOD] end def digest? diff --git a/lib/rack/body_proxy.rb b/lib/rack/body_proxy.rb index 95a74626..b35167c8 100644 --- a/lib/rack/body_proxy.rb +++ b/lib/rack/body_proxy.rb @@ -4,9 +4,14 @@ module Rack @body, @block, @closed = body, block, false end - def respond_to?(*args) - return false if args.first.to_s =~ /^to_ary$/ - super or @body.respond_to?(*args) + def respond_to?(method_name) + case method_name + when :to_ary + return false + when String + return false if /^to_ary$/ =~ method_name + end + super or @body.respond_to?(method_name) end def close diff --git a/lib/rack/cascade.rb b/lib/rack/cascade.rb index c2891e5f..6b8f415a 100644 --- a/lib/rack/cascade.rb +++ b/lib/rack/cascade.rb @@ -4,7 +4,7 @@ module Rack # status codes). class Cascade - NotFound = [404, {"Content-Type" => "text/plain"}, []] + NotFound = [404, {CONTENT_TYPE => "text/plain"}, []] attr_reader :apps diff --git a/lib/rack/chunked.rb b/lib/rack/chunked.rb index ea221fa9..36c4959d 100644 --- a/lib/rack/chunked.rb +++ b/lib/rack/chunked.rb @@ -56,11 +56,11 @@ module Rack if ! chunkable_version?(env['HTTP_VERSION']) || STATUS_WITH_NO_ENTITY_BODY.include?(status) || - headers['Content-Length'] || + headers[CONTENT_LENGTH] || headers['Transfer-Encoding'] [status, headers, body] else - headers.delete('Content-Length') + headers.delete(CONTENT_LENGTH) headers['Transfer-Encoding'] = 'chunked' [status, headers, Body.new(body)] end diff --git a/lib/rack/commonlogger.rb b/lib/rack/commonlogger.rb index 1c99045e..d2d6dc34 100644 --- a/lib/rack/commonlogger.rb +++ b/lib/rack/commonlogger.rb @@ -46,9 +46,9 @@ module Rack env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-", env["REMOTE_USER"] || "-", now.strftime("%d/%b/%Y:%H:%M:%S %z"), - env["REQUEST_METHOD"], - env["PATH_INFO"], - env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"], + env[REQUEST_METHOD], + env[PATH_INFO], + env[QUERY_STRING].empty? ? "" : "?"+env[QUERY_STRING], env["HTTP_VERSION"], status.to_s[0..3], length, @@ -65,7 +65,7 @@ module Rack end def extract_content_length(headers) - value = headers['Content-Length'] or return '-' + value = headers[CONTENT_LENGTH] or return '-' value.to_s == '0' ? '-' : value end end diff --git a/lib/rack/conditionalget.rb b/lib/rack/conditionalget.rb index 88573166..3d4c78aa 100644 --- a/lib/rack/conditionalget.rb +++ b/lib/rack/conditionalget.rb @@ -20,14 +20,14 @@ module Rack end def call(env) - case env['REQUEST_METHOD'] - when "GET", "HEAD" + case env[REQUEST_METHOD] + when GET, HEAD status, headers, body = @app.call(env) headers = Utils::HeaderHash.new(headers) if status == 200 && fresh?(env, headers) status = 304 - headers.delete('Content-Type') - headers.delete('Content-Length') + headers.delete(CONTENT_TYPE) + headers.delete(CONTENT_LENGTH) original_body = body body = Rack::BodyProxy.new([]) do original_body.close if original_body.respond_to?(:close) diff --git a/lib/rack/content_length.rb b/lib/rack/content_length.rb index 71bc919b..d0f491d1 100644 --- a/lib/rack/content_length.rb +++ b/lib/rack/content_length.rb @@ -16,7 +16,7 @@ module Rack headers = HeaderHash.new(headers) if !STATUS_WITH_NO_ENTITY_BODY.include?(status.to_i) && - !headers['Content-Length'] && + !headers[CONTENT_LENGTH] && !headers['Transfer-Encoding'] && body.respond_to?(:to_ary) @@ -28,7 +28,7 @@ module Rack obody.close if obody.respond_to?(:close) end - headers['Content-Length'] = length.to_s + headers[CONTENT_LENGTH] = length.to_s end [status, headers, body] diff --git a/lib/rack/content_type.rb b/lib/rack/content_type.rb index dd96e959..78ba43b7 100644 --- a/lib/rack/content_type.rb +++ b/lib/rack/content_type.rb @@ -20,7 +20,7 @@ module Rack headers = Utils::HeaderHash.new(headers) unless STATUS_WITH_NO_ENTITY_BODY.include?(status) - headers['Content-Type'] ||= @content_type + headers[CONTENT_TYPE] ||= @content_type end [status, headers, body] diff --git a/lib/rack/deflater.rb b/lib/rack/deflater.rb index 9df510bd..1788463b 100644 --- a/lib/rack/deflater.rb +++ b/lib/rack/deflater.rb @@ -54,20 +54,20 @@ module Rack case encoding when "gzip" headers['Content-Encoding'] = "gzip" - headers.delete('Content-Length') + headers.delete(CONTENT_LENGTH) mtime = headers.key?("Last-Modified") ? Time.httpdate(headers["Last-Modified"]) : Time.now [status, headers, GzipStream.new(body, mtime)] when "deflate" headers['Content-Encoding'] = "deflate" - headers.delete('Content-Length') + headers.delete(CONTENT_LENGTH) [status, headers, DeflateStream.new(body)] when "identity" [status, headers, body] when nil message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found." bp = Rack::BodyProxy.new([message]) { body.close if body.respond_to?(:close) } - [406, {"Content-Type" => "text/plain", "Content-Length" => message.length.to_s}, bp] + [406, {CONTENT_TYPE => "text/plain", CONTENT_LENGTH => message.length.to_s}, bp] end end @@ -138,7 +138,7 @@ module Rack # Skip compressing empty entity body responses and responses with # no-transform set. if Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) || - headers['Cache-Control'].to_s =~ /\bno-transform\b/ || + headers[CACHE_CONTROL].to_s =~ /\bno-transform\b/ || (headers['Content-Encoding'] && headers['Content-Encoding'] !~ /\bidentity\b/) return false end diff --git a/lib/rack/directory.rb b/lib/rack/directory.rb index 602f2d44..98d66e02 100644 --- a/lib/rack/directory.rb +++ b/lib/rack/directory.rb @@ -55,8 +55,8 @@ table { width:100%%; } def _call(env) @env = env - @script_name = env['SCRIPT_NAME'] - @path_info = Utils.unescape(env['PATH_INFO']) + @script_name = env[SCRIPT_NAME] + @path_info = Utils.unescape(env[PATH_INFO]) if forbidden = check_forbidden forbidden @@ -72,7 +72,7 @@ table { width:100%%; } body = "Forbidden\n" size = Rack::Utils.bytesize(body) return [403, {"Content-Type" => "text/plain", - "Content-Length" => size.to_s, + CONTENT_LENGTH => size.to_s, "X-Cascade" => "pass"}, [body]] end @@ -101,7 +101,7 @@ table { width:100%%; } @files << [ url, basename, size, type, mtime ] end - return [ 200, {'Content-Type'=>'text/html; charset=utf-8'}, self ] + return [ 200, { CONTENT_TYPE =>'text/html; charset=utf-8'}, self ] end def stat(node, max = 10) @@ -130,7 +130,7 @@ table { width:100%%; } body = "Entity not found: #{@path_info}\n" size = Rack::Utils.bytesize(body) return [404, {"Content-Type" => "text/plain", - "Content-Length" => size.to_s, + CONTENT_LENGTH => size.to_s, "X-Cascade" => "pass"}, [body]] end diff --git a/lib/rack/etag.rb b/lib/rack/etag.rb index fefe671f..88973131 100644 --- a/lib/rack/etag.rb +++ b/lib/rack/etag.rb @@ -11,6 +11,7 @@ module Rack # used when Etag is absent and a directive when it is present. The first # defaults to nil, while the second defaults to "max-age=0, private, must-revalidate" class ETag + ETAG_STRING = 'ETag'.freeze DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate".freeze def initialize(app, no_cache_control = nil, cache_control = DEFAULT_CACHE_CONTROL) @@ -28,14 +29,14 @@ module Rack body = Rack::BodyProxy.new(new_body) do original_body.close if original_body.respond_to?(:close) end - headers['ETag'] = %(W/"#{digest}") if digest + headers[ETAG_STRING] = %(W/"#{digest}") if digest end - unless headers['Cache-Control'] + unless headers[CACHE_CONTROL] if digest - headers['Cache-Control'] = @cache_control if @cache_control + headers[CACHE_CONTROL] = @cache_control if @cache_control else - headers['Cache-Control'] = @no_cache_control if @no_cache_control + headers[CACHE_CONTROL] = @no_cache_control if @no_cache_control end end @@ -53,8 +54,8 @@ module Rack end def skip_caching?(headers) - (headers['Cache-Control'] && headers['Cache-Control'].include?('no-cache')) || - headers.key?('ETag') || headers.key?('Last-Modified') + (headers[CACHE_CONTROL] && headers[CACHE_CONTROL].include?('no-cache')) || + headers.key?(ETAG_STRING) || headers.key?('Last-Modified') end def digest_body(body) diff --git a/lib/rack/file.rb b/lib/rack/file.rb index c8f8d0d1..bdae6a66 100644 --- a/lib/rack/file.rb +++ b/lib/rack/file.rb @@ -34,11 +34,11 @@ module Rack F = ::File def _call(env) - unless ALLOWED_VERBS.include? env["REQUEST_METHOD"] + unless ALLOWED_VERBS.include? env[REQUEST_METHOD] return fail(405, "Method Not Allowed", {'Allow' => ALLOW_HEADER}) end - path_info = Utils.unescape(env["PATH_INFO"]) + path_info = Utils.unescape(env[PATH_INFO]) clean_path_info = Utils.clean_path_info(path_info) @path = F.join(@root, clean_path_info) @@ -58,19 +58,19 @@ module Rack def serving(env) if env["REQUEST_METHOD"] == "OPTIONS" - return [200, {'Allow' => ALLOW_HEADER, 'Content-Length' => '0'}, []] + return [200, {'Allow' => ALLOW_HEADER, CONTENT_LENGTH => '0'}, []] end last_modified = F.mtime(@path).httpdate return [304, {}, []] if env['HTTP_IF_MODIFIED_SINCE'] == last_modified headers = { "Last-Modified" => last_modified } mime = Mime.mime_type(F.extname(@path), @default_mime) - headers["Content-Type"] = mime if mime + headers[CONTENT_TYPE] = mime if mime # Set custom headers @headers.each { |field, content| headers[field] = content } if @headers - response = [ 200, headers, env["REQUEST_METHOD"] == "HEAD" ? [] : self ] + response = [ 200, headers, env[REQUEST_METHOD] == "HEAD" ? [] : self ] # NOTE: # We check via File::size? whether this file provides size info @@ -97,7 +97,7 @@ module Rack size = @range.end - @range.begin + 1 end - response[1]["Content-Length"] = size.to_s + response[1][CONTENT_LENGTH] = size.to_s response end @@ -122,8 +122,8 @@ module Rack [ status, { - "Content-Type" => "text/plain", - "Content-Length" => body.size.to_s, + CONTENT_TYPE => "text/plain", + CONTENT_LENGTH => body.size.to_s, "X-Cascade" => "pass" }.merge!(headers), [body] diff --git a/lib/rack/handler.rb b/lib/rack/handler.rb index b5fa0268..f11e37e3 100644 --- a/lib/rack/handler.rb +++ b/lib/rack/handler.rb @@ -51,7 +51,7 @@ module Rack options.delete :Port Rack::Handler::FastCGI - elsif ENV.include?("REQUEST_METHOD") + elsif ENV.include?(REQUEST_METHOD) Rack::Handler::CGI elsif ENV.include?("RACK_HANDLER") self.get(ENV["RACK_HANDLER"]) diff --git a/lib/rack/handler/cgi.rb b/lib/rack/handler/cgi.rb index 15af1ac2..78e135e9 100644 --- a/lib/rack/handler/cgi.rb +++ b/lib/rack/handler/cgi.rb @@ -26,7 +26,7 @@ module Rack "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" }) - env["QUERY_STRING"] ||= "" + env[QUERY_STRING] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" diff --git a/lib/rack/handler/fastcgi.rb b/lib/rack/handler/fastcgi.rb index b26fabc3..5137992b 100644 --- a/lib/rack/handler/fastcgi.rb +++ b/lib/rack/handler/fastcgi.rb @@ -59,7 +59,7 @@ module Rack "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) - env["QUERY_STRING"] ||= "" + env[QUERY_STRING] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" env.delete "CONTENT_TYPE" if env["CONTENT_TYPE"] == "" diff --git a/lib/rack/handler/lsws.rb b/lib/rack/handler/lsws.rb index 1dee78a3..aec27322 100644 --- a/lib/rack/handler/lsws.rb +++ b/lib/rack/handler/lsws.rb @@ -27,7 +27,7 @@ module Rack "rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" ) - env["QUERY_STRING"] ||= "" + env[QUERY_STRING] ||= "" env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] env["REQUEST_PATH"] ||= "/" status, headers, body = app.call(env) diff --git a/lib/rack/handler/mongrel.rb b/lib/rack/handler/mongrel.rb index 20be86b1..ab9891b1 100644 --- a/lib/rack/handler/mongrel.rb +++ b/lib/rack/handler/mongrel.rb @@ -78,7 +78,7 @@ module Rack "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http" }) - env["QUERY_STRING"] ||= "" + env[QUERY_STRING] ||= "" status, headers, body = @app.call(env) diff --git a/lib/rack/handler/scgi.rb b/lib/rack/handler/scgi.rb index 40e86fb9..9a465eae 100644 --- a/lib/rack/handler/scgi.rb +++ b/lib/rack/handler/scgi.rb @@ -35,9 +35,9 @@ module Rack env = Hash[request] env.delete "HTTP_CONTENT_TYPE" env.delete "HTTP_CONTENT_LENGTH" - env["REQUEST_PATH"], env["QUERY_STRING"] = env["REQUEST_URI"].split('?', 2) + env["REQUEST_PATH"], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] - env["PATH_INFO"] = env["REQUEST_PATH"] + env[PATH_INFO] = env["REQUEST_PATH"] env["QUERY_STRING"] ||= "" env["SCRIPT_NAME"] = "" diff --git a/lib/rack/handler/webrick.rb b/lib/rack/handler/webrick.rb index 023d8b27..dcbf96ca 100644 --- a/lib/rack/handler/webrick.rb +++ b/lib/rack/handler/webrick.rb @@ -79,12 +79,12 @@ module Rack }) env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] - env["QUERY_STRING"] ||= "" - unless env["PATH_INFO"] == "" + env[QUERY_STRING] ||= "" + unless env[PATH_INFO] == "" path, n = req.request_uri.path, env["SCRIPT_NAME"].length - env["PATH_INFO"] = path[n, path.length-n] + env[PATH_INFO] = path[n, path.length-n] end - env["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env["PATH_INFO"]].join + env["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env[PATH_INFO]].join status, headers, body = @app.call(env) begin diff --git a/lib/rack/head.rb b/lib/rack/head.rb index 72f3dbdd..f487254a 100644 --- a/lib/rack/head.rb +++ b/lib/rack/head.rb @@ -12,7 +12,7 @@ class Head def call(env) status, headers, body = @app.call(env) - if env["REQUEST_METHOD"] == "HEAD" + if env[REQUEST_METHOD] == HEAD [ status, headers, Rack::BodyProxy.new([]) do body.close if body.respond_to? :close diff --git a/lib/rack/lint.rb b/lib/rack/lint.rb index 667c34a6..5cdef3f8 100644 --- a/lib/rack/lint.rb +++ b/lib/rack/lint.rb @@ -57,7 +57,7 @@ module Rack ## and the *body*. check_content_type status, headers check_content_length status, headers - @head_request = env["REQUEST_METHOD"] == "HEAD" + @head_request = env[REQUEST_METHOD] == "HEAD" [status, headers, self] end @@ -278,7 +278,7 @@ module Rack check_hijack env ## * The <tt>REQUEST_METHOD</tt> must be a valid token. - assert("REQUEST_METHOD unknown: #{env["REQUEST_METHOD"]}") { + assert("REQUEST_METHOD unknown: #{env[REQUEST_METHOD]}") { env["REQUEST_METHOD"] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/ } @@ -510,20 +510,20 @@ module Rack ## already present, in rack.hijack_io. io = original_hijack.call HijackWrapper.new(io) - ## + ## ## rack.hijack_io must respond to: ## <tt>read, write, read_nonblock, write_nonblock, flush, close, ## close_read, close_write, closed?</tt> - ## + ## ## The semantics of these IO methods must be a best effort match to ## those of a normal ruby IO or Socket object, using standard ## arguments and raising standard exceptions. Servers are encouraged ## to simply pass on real IO objects, although it is recognized that ## this approach is not directly compatible with SPDY and HTTP 2.0. - ## + ## ## IO provided in rack.hijack_io should preference the ## IO::WaitReadable and IO::WaitWritable APIs wherever supported. - ## + ## ## There is a deliberate lack of full specification around ## rack.hijack_io, as semantics will change from server to server. ## Users are encouraged to utilize this API with a knowledge of their @@ -535,10 +535,10 @@ module Rack io end else - ## + ## ## If rack.hijack? is false, then rack.hijack should not be set. assert("rack.hijack? is false, but rack.hijack is present") { env['rack.hijack'].nil? } - ## + ## ## If rack.hijack? is false, then rack.hijack_io should not be set. assert("rack.hijack? is false, but rack.hijack_io is present") { env['rack.hijack_io'].nil? } end @@ -557,7 +557,7 @@ module Rack ## <tt>rack.hijack</tt> to an object that responds to <tt>call</tt> ## accepting an argument that conforms to the <tt>rack.hijack_io</tt> ## protocol. - ## + ## ## After the headers have been sent, and this hijack callback has been ## called, the application is now responsible for the remaining lifecycle ## of the IO. The application is also responsible for maintaining HTTP @@ -566,7 +566,7 @@ module Rack ## HTTP/1.1, and not Connection:keep-alive, as there is no protocol for ## returning hijacked sockets to the web server. For that purpose, use the ## body streaming API instead (progressively yielding strings via each). - ## + ## ## Servers must ignore the <tt>body</tt> part of the response tuple when ## the <tt>rack.hijack</tt> response API is in use. @@ -579,7 +579,7 @@ module Rack original_hijack.call HijackWrapper.new(io) end else - ## + ## ## The special response header <tt>rack.hijack</tt> must only be set ## if the request env has <tt>rack.hijack?</tt> <tt>true</tt>. assert('rack.hijack header must not be present if server does not support hijacking') { diff --git a/lib/rack/lobster.rb b/lib/rack/lobster.rb index 195bd945..b7d15278 100644 --- a/lib/rack/lobster.rb +++ b/lib/rack/lobster.rb @@ -12,7 +12,7 @@ module Rack I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0]) LambdaLobster = lambda { |env| - if env["QUERY_STRING"].include?("flip") + if env[QUERY_STRING].include?("flip") lobster = LobsterString.split("\n"). map { |line| line.ljust(42).reverse }. join("\n") @@ -26,7 +26,7 @@ module Rack "<pre>", lobster, "</pre>", "<a href='#{href}'>flip!</a>"] length = content.inject(0) { |a,e| a+e.size }.to_s - [200, {"Content-Type" => "text/html", "Content-Length" => length}, content] + [200, {CONTENT_TYPE => "text/html", CONTENT_LENGTH => length}, content] } def call(env) diff --git a/lib/rack/methodoverride.rb b/lib/rack/methodoverride.rb index 062f3d67..7d2b56eb 100644 --- a/lib/rack/methodoverride.rb +++ b/lib/rack/methodoverride.rb @@ -11,11 +11,11 @@ module Rack end def call(env) - if allowed_methods.include?(env["REQUEST_METHOD"]) + if allowed_methods.include?(env[REQUEST_METHOD]) method = method_override(env) if HTTP_METHODS.include?(method) - env["rack.methodoverride.original_method"] = env["REQUEST_METHOD"] - env["REQUEST_METHOD"] = method + env["rack.methodoverride.original_method"] = env[REQUEST_METHOD] + env[REQUEST_METHOD] = method end end diff --git a/lib/rack/mock.rb b/lib/rack/mock.rb index 3c02c1fe..217ae0f7 100644 --- a/lib/rack/mock.rb +++ b/lib/rack/mock.rb @@ -91,15 +91,15 @@ module Rack env = DEFAULT_ENV.dup - env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "GET" + env[REQUEST_METHOD] = opts[:method] ? opts[:method].to_s.upcase : "GET" env["SERVER_NAME"] = uri.host || "example.org" env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80" - env["QUERY_STRING"] = uri.query.to_s - env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path + env[QUERY_STRING] = uri.query.to_s + env[PATH_INFO] = (!uri.path || uri.path.empty?) ? "/" : uri.path env["rack.url_scheme"] = uri.scheme || "http" env["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off" - env["SCRIPT_NAME"] = opts[:script_name] || "" + env[SCRIPT_NAME] = opts[:script_name] || "" if opts[:fatal] env["rack.errors"] = FatalWarner.new @@ -108,10 +108,10 @@ module Rack end if params = opts[:params] - if env["REQUEST_METHOD"] == "GET" + if env[REQUEST_METHOD] == "GET" params = Utils.parse_nested_query(params) if params.is_a?(String) - params.update(Utils.parse_nested_query(env["QUERY_STRING"])) - env["QUERY_STRING"] = Utils.build_nested_query(params) + params.update(Utils.parse_nested_query(env[QUERY_STRING])) + env[QUERY_STRING] = Utils.build_nested_query(params) elsif !opts.has_key?(:input) opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded" if params.is_a?(Hash) diff --git a/lib/rack/recursive.rb b/lib/rack/recursive.rb index b431d4dd..17d17dfd 100644 --- a/lib/rack/recursive.rb +++ b/lib/rack/recursive.rb @@ -14,8 +14,8 @@ module Rack @url = URI(url) @env = env - @env["PATH_INFO"] = @url.path - @env["QUERY_STRING"] = @url.query if @url.query + @env[PATH_INFO] = @url.path + @env[QUERY_STRING] = @url.query if @url.query @env["HTTP_HOST"] = @url.host if @url.host @env["HTTP_PORT"] = @url.port if @url.port @env["rack.url_scheme"] = @url.scheme if @url.scheme @@ -39,7 +39,7 @@ module Rack end def _call(env) - @script_name = env["SCRIPT_NAME"] + @script_name = env[SCRIPT_NAME] @app.call(env.merge('rack.recursive.include' => method(:include))) rescue ForwardRequest => req call(env.merge(req.env)) @@ -51,8 +51,9 @@ module Rack raise ArgumentError, "can only include below #{@script_name}, not #{path}" end - env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name, - "REQUEST_METHOD" => "GET", + env = env.merge(PATH_INFO => path, + SCRIPT_NAME => @script_name, + REQUEST_METHOD => "GET", "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "", "rack.input" => StringIO.new("")) @app.call(env) diff --git a/lib/rack/request.rb b/lib/rack/request.rb index 602d0d64..e6e46e9d 100644 --- a/lib/rack/request.rb +++ b/lib/rack/request.rb @@ -18,10 +18,10 @@ module Rack end def body; @env["rack.input"] end - def script_name; @env["SCRIPT_NAME"].to_s end - def path_info; @env["PATH_INFO"].to_s end + def script_name; @env[SCRIPT_NAME].to_s end + def path_info; @env[PATH_INFO].to_s end def request_method; @env["REQUEST_METHOD"] end - def query_string; @env["QUERY_STRING"].to_s end + def query_string; @env[QUERY_STRING].to_s end def content_length; @env['CONTENT_LENGTH'] end def content_type @@ -116,10 +116,10 @@ module Rack def delete?; request_method == "DELETE" end # Checks the HTTP request method (or verb) to see if it was of type GET - def get?; request_method == "GET" end + def get?; request_method == GET end # Checks the HTTP request method (or verb) to see if it was of type HEAD - def head?; request_method == "HEAD" end + def head?; request_method == HEAD end # Checks the HTTP request method (or verb) to see if it was of type OPTIONS def options?; request_method == "OPTIONS" end @@ -173,7 +173,7 @@ module Rack # Content-Type header is provided and the request_method is POST. def form_data? type = media_type - meth = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'] + meth = env["rack.methodoverride.original_method"] || env[REQUEST_METHOD] (meth == 'POST' && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type) end diff --git a/lib/rack/response.rb b/lib/rack/response.rb index 12536710..7f0c6b71 100644 --- a/lib/rack/response.rb +++ b/lib/rack/response.rb @@ -20,11 +20,13 @@ module Rack class Response attr_accessor :length + CHUNKED = 'chunked'.freeze + TRANSFER_ENCODING = 'Transfer-Encoding'.freeze def initialize(body=[], status=200, header={}) @status = status.to_i @header = Utils::HeaderHash.new.merge(header) - @chunked = "chunked" == @header['Transfer-Encoding'] + @chunked = CHUNKED == @header[TRANSFER_ENCODING] @writer = lambda { |x| @body << x } @block = nil @length = 0 @@ -72,8 +74,8 @@ module Rack @block = block if [204, 205, 304].include?(status.to_i) - header.delete "Content-Type" - header.delete "Content-Length" + header.delete CONTENT_TYPE + header.delete CONTENT_LENGTH close [status.to_i, header, []] else @@ -98,7 +100,7 @@ module Rack @length += Rack::Utils.bytesize(s) unless @chunked @writer.call s - header["Content-Length"] = @length.to_s unless @chunked + header[CONTENT_LENGTH] = @length.to_s unless @chunked str end @@ -142,11 +144,11 @@ module Rack end def content_type - headers["Content-Type"] + headers[CONTENT_TYPE] end def content_length - cl = headers["Content-Length"] + cl = headers[CONTENT_LENGTH] cl ? cl.to_i : cl end diff --git a/lib/rack/runtime.rb b/lib/rack/runtime.rb index 1bd411fd..83d6c0ca 100644 --- a/lib/rack/runtime.rb +++ b/lib/rack/runtime.rb @@ -12,13 +12,14 @@ module Rack @header_name << "-#{name}" if name end + FORMAT_STRING = "%0.6f" def call(env) start_time = Time.now status, headers, body = @app.call(env) request_time = Time.now - start_time if !headers.has_key?(@header_name) - headers[@header_name] = "%0.6f" % request_time + headers[@header_name] = FORMAT_STRING % request_time end [status, headers, body] diff --git a/lib/rack/sendfile.rb b/lib/rack/sendfile.rb index 8e2c3d67..4a9b428b 100644 --- a/lib/rack/sendfile.rb +++ b/lib/rack/sendfile.rb @@ -116,7 +116,7 @@ module Rack when 'X-Accel-Redirect' path = F.expand_path(body.to_path) if url = map_accel_path(env, path) - headers['Content-Length'] = '0' + headers[CONTENT_LENGTH] = '0' headers[type] = url obody = body body = Rack::BodyProxy.new([]) do @@ -127,7 +127,7 @@ module Rack end when 'X-Sendfile', 'X-Lighttpd-Send-File' path = F.expand_path(body.to_path) - headers['Content-Length'] = '0' + headers[CONTENT_LENGTH] = '0' headers[type] = path obody = body body = Rack::BodyProxy.new([]) do diff --git a/lib/rack/server.rb b/lib/rack/server.rb index d9f971d7..ea1ad82b 100644 --- a/lib/rack/server.rb +++ b/lib/rack/server.rb @@ -310,7 +310,7 @@ module Rack # Don't evaluate CGI ISINDEX parameters. # http://www.meb.uni-bonn.de/docs/cgi/cl.html - args.clear if ENV.include?("REQUEST_METHOD") + args.clear if ENV.include?(REQUEST_METHOD) options.merge! opt_parser.parse!(args) options[:config] = ::File.expand_path(options[:config]) diff --git a/lib/rack/showexceptions.rb b/lib/rack/showexceptions.rb index 731aea49..60999e64 100644 --- a/lib/rack/showexceptions.rb +++ b/lib/rack/showexceptions.rb @@ -39,8 +39,8 @@ module Rack [ 500, { - "Content-Type" => content_type, - "Content-Length" => Rack::Utils.bytesize(body).to_s, + CONTENT_TYPE => content_type, + CONTENT_LENGTH => Rack::Utils.bytesize(body).to_s, }, [body], ] diff --git a/lib/rack/showstatus.rb b/lib/rack/showstatus.rb index 6892a5b7..4426310a 100644 --- a/lib/rack/showstatus.rb +++ b/lib/rack/showstatus.rb @@ -3,7 +3,7 @@ require 'rack/request' require 'rack/utils' module Rack - # Rack::ShowStatus catches all empty responses and replaces them + # Rack::ShowStatus catches all empty responses and replaces them # with a site explaining the error. # # Additional details can be put into <tt>rack.showstatus.detail</tt> @@ -19,7 +19,7 @@ module Rack def call(env) status, headers, body = @app.call(env) headers = Utils::HeaderHash.new(headers) - empty = headers['Content-Length'].to_i <= 0 + empty = headers[CONTENT_LENGTH].to_i <= 0 # client or server error, or explicit message if (status.to_i >= 400 && empty) || env["rack.showstatus.detail"] @@ -35,7 +35,7 @@ module Rack body = @template.result(binding) size = Rack::Utils.bytesize(body) - [status, headers.merge("Content-Type" => "text/html", "Content-Length" => size.to_s), [body]] + [status, headers.merge(CONTENT_TYPE => "text/html", CONTENT_LENGTH => size.to_s), [body]] else [status, headers, body] end diff --git a/lib/rack/static.rb b/lib/rack/static.rb index 41aec7f3..75e1e555 100644 --- a/lib/rack/static.rb +++ b/lib/rack/static.rb @@ -107,7 +107,7 @@ module Rack end def call(env) - path = env["PATH_INFO"] + path = env[PATH_INFO] if can_serve(path) env["PATH_INFO"] = (path =~ /\/$/ ? path + @index : @urls[path]) if overwrite_file_path(path) diff --git a/lib/rack/urlmap.rb b/lib/rack/urlmap.rb index d75f5a22..c62baecc 100644 --- a/lib/rack/urlmap.rb +++ b/lib/rack/urlmap.rb @@ -41,7 +41,7 @@ module Rack end def call(env) - path = env['PATH_INFO'] + path = env[PATH_INFO] script_name = env['SCRIPT_NAME'] hHost = env['HTTP_HOST'] sName = env['SERVER_NAME'] @@ -66,7 +66,7 @@ module Rack return app.call(env) end - [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]] + [404, {CONTENT_TYPE => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]] ensure env['PATH_INFO'] = path |