From 0a41a94d9a2d5bbfcabf1fde5d197e794d6724cc Mon Sep 17 00:00:00 2001 From: Ryan Tomayko Date: Thu, 5 Mar 2009 21:19:23 -0800 Subject: [PATCH] Add Rack::Utils.bytesize function, use everywhere --- lib/rack/content_length.rb | 8 +++++--- lib/rack/deflater.rb | 4 ++-- lib/rack/directory.rb | 4 ++-- lib/rack/lint.rb | 2 +- lib/rack/showstatus.rb | 2 +- lib/rack/utils.rb | 13 +++++++++++++ test/spec_rack_utils.rb | 4 ++++ 7 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/rack/content_length.rb b/lib/rack/content_length.rb index bce22a3..1e56d43 100644 --- a/lib/rack/content_length.rb +++ b/lib/rack/content_length.rb @@ -3,21 +3,23 @@ require 'rack/utils' module Rack # Sets the Content-Length header on responses with fixed-length bodies. class ContentLength + include Rack::Utils + def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) - headers = Utils::HeaderHash.new(headers) + headers = HeaderHash.new(headers) - if !Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) && + if !STATUS_WITH_NO_ENTITY_BODY.include?(status) && !headers['Content-Length'] && !headers['Transfer-Encoding'] && (body.respond_to?(:to_ary) || body.respond_to?(:to_str)) body = [body] if body.respond_to?(:to_str) # rack 0.4 compat - length = body.to_ary.inject(0) { |len, part| len + part.length } + length = body.to_ary.inject(0) { |len, part| len + bytesize(part) } headers['Content-Length'] = length.to_s end diff --git a/lib/rack/deflater.rb b/lib/rack/deflater.rb index 3e66680..a42b747 100644 --- a/lib/rack/deflater.rb +++ b/lib/rack/deflater.rb @@ -36,12 +36,12 @@ module Rack mtime = headers.key?("Last-Modified") ? Time.httpdate(headers["Last-Modified"]) : Time.now body = self.class.gzip(body, mtime) - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) headers = headers.merge("Content-Encoding" => "gzip", "Content-Length" => size.to_s) [status, headers, [body]] when "deflate" body = self.class.deflate(body) - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) headers = headers.merge("Content-Encoding" => "deflate", "Content-Length" => size.to_s) [status, headers, [body]] when "identity" diff --git a/lib/rack/directory.rb b/lib/rack/directory.rb index 0f37df3..acdd302 100644 --- a/lib/rack/directory.rb +++ b/lib/rack/directory.rb @@ -70,7 +70,7 @@ table { width:100%%; } return unless @path_info.include? ".." body = "Forbidden\n" - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) return [403, {"Content-Type" => "text/plain","Content-Length" => size.to_s}, [body]] end @@ -122,7 +122,7 @@ table { width:100%%; } def entity_not_found body = "Entity not found: #{@path_info}\n" - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) return [404, {"Content-Type" => "text/plain", "Content-Length" => size.to_s}, [body]] end diff --git a/lib/rack/lint.rb b/lib/rack/lint.rb index 7eb0543..e549a9e 100644 --- a/lib/rack/lint.rb +++ b/lib/rack/lint.rb @@ -401,7 +401,7 @@ module Rack break end - bytes += (part.respond_to?(:bytesize) ? part.bytesize : part.size) + bytes += Rack::Utils.bytesize(part) } if env["REQUEST_METHOD"] == "HEAD" diff --git a/lib/rack/showstatus.rb b/lib/rack/showstatus.rb index 5f13404..28258c7 100644 --- a/lib/rack/showstatus.rb +++ b/lib/rack/showstatus.rb @@ -27,7 +27,7 @@ module Rack message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s detail = env["rack.showstatus.detail"] || message body = @template.result(binding) - size = body.respond_to?(:bytesize) ? body.bytesize : body.size + size = Rack::Utils.bytesize(body) [status, headers.merge("Content-Type" => "text/html", "Content-Length" => size.to_s), [body]] else [status, headers, body] diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb index f352cb6..e86d4cc 100644 --- a/lib/rack/utils.rb +++ b/lib/rack/utils.rb @@ -144,6 +144,19 @@ module Rack end module_function :select_best_encoding + # Return the bytesize of String; uses String#length under Ruby 1.8 and + # String#bytesize under 1.9. + if ''.respond_to?(:bytesize) + def bytesize(string) + string.bytesize + end + else + def bytesize(string) + string.size + end + end + module_function :bytesize + # Context allows the use of a compatible middleware at different points # in a request handling stack. A compatible middleware must define # #context which should take the arguments env and app. The first of which diff --git a/test/spec_rack_utils.rb b/test/spec_rack_utils.rb index f0f90d9..82016b8 100644 --- a/test/spec_rack_utils.rb +++ b/test/spec_rack_utils.rb @@ -129,6 +129,10 @@ context "Rack::Utils" do helper.call(%w(foo bar identity), [["foo", 0], ["bar", 0]]).should.equal("identity") helper.call(%w(foo bar baz identity), [["*", 0], ["identity", 0.1]]).should.equal("identity") end + + specify "should return the bytesize of String" do + Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6 + end end context "Rack::Utils::HeaderHash" do -- 1.6.2