diff options
author | Christian Neukirchen <chneukirchen@gmail.com> | 2008-08-17 12:40:00 +0200 |
---|---|---|
committer | Christian Neukirchen <chneukirchen@gmail.com> | 2008-08-17 12:40:00 +0200 |
commit | f0977a8a204fc1074f0d0211d0bdcc258feb5735 (patch) | |
tree | 60be2a496a4e22846b2d3bce1673e8ee4cff6539 | |
parent | e9f9f27ac772de7db0ba33e0421c7ffccbdbade1 (diff) | |
download | rack-f0977a8a204fc1074f0d0211d0bdcc258feb5735.tar.gz |
Disarm and document Content-Length checking in Rack::Lint for 0.4
-rw-r--r-- | README | 16 | ||||
-rw-r--r-- | lib/rack/lint.rb | 62 | ||||
-rw-r--r-- | test/spec_rack_lint.rb | 41 |
3 files changed, 19 insertions, 100 deletions
@@ -9,6 +9,21 @@ middleware) into a single method call. The exact details of this are described in the Rack specification, which all Rack applications should conform to. +== Future specification changes + +PLEASE NOTE: In versions of Rack LATER than 0.4, the following +changes will be commited to the specification: + +* 1xx, 204 and 304 status codes MUST not contain a Content-Type. +* A valid Content-Length header MUST be provided for non 1xx, 204 and 304 + responses with an Transfer-Encoding of "identity" (default). + The Content-Length MUST be the same as the sum of the byte-sizes of + the chunks. + +Internal Rack modules have been updated to follow this behavior, but +the Rack 0.4 Lint does NOT check it yet for compatibility reasons. +Please update your libraries accordingly. + == Supported web servers The included *handlers* connect all kinds of web servers to Rack: @@ -160,7 +175,6 @@ Installing the Ruby fcgi gem: Furthermore, to test Memcache sessions, you need memcached (will be run on port 11211) and memcache-client installed. - == History * March 3rd, 2007: First public release 0.1. diff --git a/lib/rack/lint.rb b/lib/rack/lint.rb index 2b81f10d..7bc433b8 100644 --- a/lib/rack/lint.rb +++ b/lib/rack/lint.rb @@ -3,8 +3,6 @@ module Rack # responses according to the Rack spec. class Lint - STATUS_WITH_NO_ENTITY_BODY = (100..199).to_a << 204 << 304 - def initialize(app) @app = app end @@ -51,7 +49,6 @@ module Rack check_headers headers ## and the *body*. check_content_type status, headers - check_content_length status, headers [status, headers, self] end @@ -353,69 +350,18 @@ module Rack def check_content_type(status, headers) headers.each { |key, value| ## There must be a <tt>Content-Type</tt>, except when the - ## +Status+ is 1xx, 204 or 304, in which case there must be none + ## +Status+ is 204 or 304, in which case there must be none ## given. if key.downcase == "content-type" - assert("Content-Type header found in #{status} response, not allowed") { - not STATUS_WITH_NO_ENTITY_BODY.include? status.to_i + assert("Content-Type header found in #{status} response, not allowed"){ + not [204, 304].include? status.to_i } return end } assert("No Content-Type header found") { - STATUS_WITH_NO_ENTITY_BODY.include? status.to_i - } - end - - ## === The Content-Length - def check_content_length(status, headers) - chunked_response = false - headers.each { |key, value| - if key.downcase == 'transfer-encoding' - chunked_response = value.downcase != 'identity' - end + [204, 304].include? status.to_i } - - headers.each { |key, value| - if key.downcase == 'content-length' - ## There must be a <tt>Content-Length</tt>, except when the - ## +Status+ is 1xx, 204 or 304, in which case there must be none - ## given. - assert("Content-Length header found in #{status} response, not allowed") { - not STATUS_WITH_NO_ENTITY_BODY.include? status.to_i - } - - assert('Content-Length header should not be used if body is chunked') { - not chunked_response - } - - bytes = 0 - string_body = true - - @body.each { |part| - unless part.kind_of?(String) - string_body = false - break - end - - bytes += (part.respond_to?(:bytesize) ? part.bytesize : part.size) - } - - if string_body - assert("Content-Length header was #{value}, but should be #{bytes}") { - value == bytes.to_s - } - end - - return - end - } - - if [ String, Array ].include?(@body.class) && !chunked_response - assert('No Content-Length header found') { - STATUS_WITH_NO_ENTITY_BODY.include? status.to_i - } - end end ## === The Body diff --git a/test/spec_rack_lint.rb b/test/spec_rack_lint.rb index a8112b85..dbb6687e 100644 --- a/test/spec_rack_lint.rb +++ b/test/spec_rack_lint.rb @@ -203,47 +203,6 @@ context "Rack::Lint" do }).call(env({})) }.should.raise(Rack::Lint::LintError). message.should.match(/No Content-Type/) - - [100, 101, 204, 304].each do |status| - lambda { - Rack::Lint.new(lambda { |env| - [status, {"Content-type" => "text/plain", "Content-length" => "0"}, ""] - }).call(env({})) - }.should.raise(Rack::Lint::LintError). - message.should.match(/Content-Type header found/) - end - end - - specify "notices content-length errors" do - lambda { - Rack::Lint.new(lambda { |env| - [200, {"Content-type" => "text/plain"}, ""] - }).call(env({})) - }.should.raise(Rack::Lint::LintError). - message.should.match(/No Content-Length/) - - [100, 101, 204, 304].each do |status| - lambda { - Rack::Lint.new(lambda { |env| - [status, {"Content-length" => "0"}, ""] - }).call(env({})) - }.should.raise(Rack::Lint::LintError). - message.should.match(/Content-Length header found/) - end - - lambda { - Rack::Lint.new(lambda { |env| - [200, {"Content-type" => "text/plain", "Content-Length" => "0", "Transfer-Encoding" => "chunked"}, ""] - }).call(env({})) - }.should.raise(Rack::Lint::LintError). - message.should.match(/Content-Length header should not be used/) - - lambda { - Rack::Lint.new(lambda { |env| - [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, ""] - }).call(env({})) - }.should.raise(Rack::Lint::LintError). - message.should.match(/Content-Length header was 1, but should be 0/) end specify "notices body errors" do |