From 32a7b63a0c54b6376a1a9e2affde515145b4e715 Mon Sep 17 00:00:00 2001 From: Geoff Buesing Date: Sun, 17 Jan 2010 10:48:15 -0600 Subject: [PATCH] Rack::DefaultCharset - Adds the specified charset to the Content-Type header if one isn't already there --- README.rdoc | 1 + lib/rack/contrib.rb | 1 + lib/rack/contrib/default_charset.rb | 25 ++++++++++++++++++ test/spec_rack_default_charset.rb | 49 +++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 0 deletions(-) create mode 100644 lib/rack/contrib/default_charset.rb create mode 100644 test/spec_rack_default_charset.rb diff --git a/README.rdoc b/README.rdoc index ca015ae..f706b38 100644 --- a/README.rdoc +++ b/README.rdoc @@ -46,6 +46,7 @@ interface: * Rack::HostMeta - Configures /host-meta using a block * Rack::Cookies - Adds simple cookie jar hash to env * Rack::Access - Limit access based on IP address +* Rack::DefaultCharset - Adds the specified charset to the Content-Type header if one isn't already there === Use diff --git a/lib/rack/contrib.rb b/lib/rack/contrib.rb index 8905437..4147890 100644 --- a/lib/rack/contrib.rb +++ b/lib/rack/contrib.rb @@ -12,6 +12,7 @@ module Rack autoload :BounceFavicon, "rack/contrib/bounce_favicon" autoload :Cookies, "rack/contrib/cookies" autoload :CSSHTTPRequest, "rack/contrib/csshttprequest" + autoload :DefaultCharset, "rack/contrib/default_charset" autoload :Deflect, "rack/contrib/deflect" autoload :ETag, "rack/contrib/etag" autoload :ExpectationCascade, "rack/contrib/expectation_cascade" diff --git a/lib/rack/contrib/default_charset.rb b/lib/rack/contrib/default_charset.rb new file mode 100644 index 0000000..bd50f7e --- /dev/null +++ b/lib/rack/contrib/default_charset.rb @@ -0,0 +1,25 @@ +module Rack + # Adds the specified charset to the Content-Type header, if one isn't + # already there. + # + # Ideal for use with Sinatra, which by default doesn't set charset + class DefaultCharset + HAS_CHARSET = /;\s*charset\s*=\s*/i + + def initialize(app, value = 'utf-8') + @app = app + @value = "; charset=#{value}" + end + + def call(env) + response = @app.call(env) + headers = Utils::HeaderHash.new(response[1]) + content_type = headers['Content-Type'] + if content_type && content_type !~ HAS_CHARSET + content_type << @value + end + response[1] = headers + response + end + end +end diff --git a/test/spec_rack_default_charset.rb b/test/spec_rack_default_charset.rb new file mode 100644 index 0000000..03614b7 --- /dev/null +++ b/test/spec_rack_default_charset.rb @@ -0,0 +1,49 @@ +require 'test/spec' +require 'rack' +require 'rack/contrib/default_charset' + +context "Rack::DefaultCharset" do + + specify "adds utf-8 charset by default" do + app = Proc.new { [200, {'Content-Type' => 'text/html'}, []]} + middleware = Rack::DefaultCharset.new(app) + status, headers, body = middleware.call({}) + headers['Content-Type'].should == 'text/html; charset=utf-8' + end + + specify "adds specified charset" do + app = Proc.new { [200, {'Content-Type' => 'text/html'}, []]} + middleware = Rack::DefaultCharset.new(app, 'us-ascii') + status, headers, body = middleware.call({}) + headers['Content-Type'].should == 'text/html; charset=us-ascii' + end + + specify "adds specified charset when Content-Type header name is downcased" do + app = Proc.new { [200, {'content-type' => "text/html"}, []]} + middleware = Rack::DefaultCharset.new(app, 'us-ascii') + status, headers, body = middleware.call({}) + headers['Content-Type'].should == "text/html; charset=us-ascii" + end + + specify "does not overwrite existing charset value" do + app = Proc.new { [200, {'Content-Type' => 'text/html; charset=us-ascii'}, []]} + middleware = Rack::DefaultCharset.new(app, 'iso-8859-2') + status, headers, body = middleware.call({}) + headers['Content-Type'].should == 'text/html; charset=us-ascii' + end + + specify "does not overwrite existing charset value when charset has odd spacing" do + app = Proc.new { [200, {'Content-Type' => 'text/html;charset = us-ascii'}, []]} + middleware = Rack::DefaultCharset.new(app, 'iso-8859-2') + status, headers, body = middleware.call({}) + headers['Content-Type'].should == 'text/html;charset = us-ascii' + end + + specify "does not overwrite existing charset value when charset has odd casing" do + app = Proc.new { [200, {'Content-type' => 'text/html; chaRSet=us-ascii'}, []]} + middleware = Rack::DefaultCharset.new(app, 'iso-8859-2') + status, headers, body = middleware.call({}) + headers['Content-Type'].should == 'text/html; chaRSet=us-ascii' + end + +end -- 1.6.1