Skip to content
This repository
Browse code

Implemented Rack::Head, modified Rack::Lint to ensure responses to HE…

…AD requests have empty bodies
  • Loading branch information...
commit 8b784d3f00432547fa3fb45defe09fa384792eb5 1 parent 6874dab
Ben Alpert spicyj authored chneukirchen committed
1  lib/rack.rb
@@ -35,6 +35,7 @@ def self.release
35 35 autoload :Directory, "rack/directory"
36 36 autoload :ForwardRequest, "rack/recursive"
37 37 autoload :Handler, "rack/handler"
  38 + autoload :Head, "rack/head"
38 39 autoload :Lint, "rack/lint"
39 40 autoload :MethodOverride, "rack/methodoverride"
40 41 autoload :Mime, "rack/mime"
19 lib/rack/head.rb
... ... @@ -0,0 +1,19 @@
  1 +module Rack
  2 +
  3 +class Head
  4 + def initialize(app)
  5 + @app = app
  6 + end
  7 +
  8 + def call(env)
  9 + status, headers, body = @app.call(env)
  10 +
  11 + if env["REQUEST_METHOD"] == "HEAD"
  12 + [status, headers, []]
  13 + else
  14 + [status, headers, body]
  15 + end
  16 + end
  17 +end
  18 +
  19 +end
16 lib/rack/lint.rb
@@ -51,7 +51,7 @@ def _call(env)
51 51 check_headers headers
52 52 ## and the *body*.
53 53 check_content_type status, headers
54   - check_content_length status, headers
  54 + check_content_length status, headers, env
55 55 [status, headers, self]
56 56 end
57 57
@@ -370,7 +370,7 @@ def check_content_type(status, headers)
370 370 end
371 371
372 372 ## === The Content-Length
373   - def check_content_length(status, headers)
  373 + def check_content_length(status, headers, env)
374 374 chunked_response = false
375 375 headers.each { |key, value|
376 376 if key.downcase == 'transfer-encoding'
@@ -403,10 +403,16 @@ def check_content_length(status, headers)
403 403 bytes += (part.respond_to?(:bytesize) ? part.bytesize : part.size)
404 404 }
405 405
406   - if string_body
407   - assert("Content-Length header was #{value}, but should be #{bytes}") {
408   - value == bytes.to_s
  406 + if env["REQUEST_METHOD"] == "HEAD"
  407 + assert("Response body was given for HEAD request, but should be empty") {
  408 + bytes == 0
409 409 }
  410 + else
  411 + if string_body
  412 + assert("Content-Length header was #{value}, but should be #{bytes}") {
  413 + value == bytes.to_s
  414 + }
  415 + end
410 416 end
411 417
412 418 return
30 test/spec_rack_head.rb
... ... @@ -0,0 +1,30 @@
  1 +require 'rack/head'
  2 +require 'rack/mock'
  3 +
  4 +context "Rack::Head" do
  5 + def test_response(headers = {})
  6 + app = lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] }
  7 + request = Rack::MockRequest.env_for("/", headers)
  8 + response = Rack::Head.new(app).call(request)
  9 +
  10 + return response
  11 + end
  12 +
  13 + specify "passes GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do
  14 + %w[GET POST PUT DELETE OPTIONS TRACE].each do |type|
  15 + resp = test_response("REQUEST_METHOD" => type)
  16 +
  17 + resp[0].should.equal(200)
  18 + resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
  19 + resp[2].should.equal(["foo"])
  20 + end
  21 + end
  22 +
  23 + specify "removes body from HEAD requests" do
  24 + resp = test_response("REQUEST_METHOD" => "HEAD")
  25 +
  26 + resp[0].should.equal(200)
  27 + resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
  28 + resp[2].should.equal([])
  29 + end
  30 +end
15 test/spec_rack_lint.rb
@@ -340,6 +340,21 @@ def each
340 340 }.should.raise(Rack::Lint::LintError).
341 341 message.should.match(/close must not be called/)
342 342 end
  343 +
  344 + specify "notices HEAD errors" do
  345 + lambda {
  346 + Rack::Lint.new(lambda { |env|
  347 + [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []]
  348 + }).call(env({"REQUEST_METHOD" => "HEAD"}))
  349 + }.should.not.raise
  350 +
  351 + lambda {
  352 + Rack::Lint.new(lambda { |env|
  353 + [200, {"Content-type" => "test/plain", "Content-length" => "3"}, "foo"]
  354 + }).call(env({"REQUEST_METHOD" => "HEAD"}))
  355 + }.should.raise(Rack::Lint::LintError).
  356 + message.should.match(/body was given for HEAD/)
  357 + end
343 358 end
344 359
345 360 context "Rack::Lint::InputWrapper" do

0 comments on commit 8b784d3

Please sign in to comment.
Something went wrong with that request. Please try again.