spec_chunked.rb 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. require 'rack/chunked'
  2. require 'rack/lint'
  3. require 'rack/mock'
  4. describe Rack::Chunked do
  5. Enumerator = ::Enumerable::Enumerator unless defined?(Enumerator)
  6. def chunked(app)
  7. proc do |env|
  8. app = Rack::Chunked.new(app)
  9. Rack::Lint.new(app).call(env).tap do |response|
  10. # we want to use body like an array, but it only has #each
  11. response[2] = Enumerator.new(response[2]).to_a
  12. end
  13. end
  14. end
  15. before do
  16. @env = Rack::MockRequest.
  17. env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
  18. end
  19. should 'chunk responses with no Content-Length' do
  20. app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
  21. response = Rack::MockResponse.new(*chunked(app).call(@env))
  22. response.headers.should.not.include 'Content-Length'
  23. response.headers['Transfer-Encoding'].should.equal 'chunked'
  24. response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
  25. end
  26. should 'chunks empty bodies properly' do
  27. app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
  28. response = Rack::MockResponse.new(*chunked(app).call(@env))
  29. response.headers.should.not.include 'Content-Length'
  30. response.headers['Transfer-Encoding'].should.equal 'chunked'
  31. response.body.should.equal "0\r\n\r\n"
  32. end
  33. should 'chunks encoded bodies properly' do
  34. body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
  35. app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
  36. response = Rack::MockResponse.new(*chunked(app).call(@env))
  37. response.headers.should.not.include 'Content-Length'
  38. response.headers['Transfer-Encoding'].should.equal 'chunked'
  39. response.body.encoding.to_s.should == "ASCII-8BIT"
  40. response.body.should.equal "c\r\n\xFE\xFFH\x00e\x00l\x00l\x00o\x00\r\n2\r\n \x00\r\na\r\nW\x00o\x00r\x00l\x00d\x00\r\n0\r\n\r\n"
  41. end if RUBY_VERSION >= "1.9"
  42. should 'not modify response when Content-Length header present' do
  43. app = lambda { |env|
  44. [200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']]
  45. }
  46. status, headers, body = chunked(app).call(@env)
  47. status.should.equal 200
  48. headers.should.not.include 'Transfer-Encoding'
  49. headers.should.include 'Content-Length'
  50. body.join.should.equal 'Hello World!'
  51. end
  52. should 'not modify response when client is HTTP/1.0' do
  53. app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
  54. @env['HTTP_VERSION'] = 'HTTP/1.0'
  55. status, headers, body = chunked(app).call(@env)
  56. status.should.equal 200
  57. headers.should.not.include 'Transfer-Encoding'
  58. body.join.should.equal 'Hello World!'
  59. end
  60. should 'not modify response when Transfer-Encoding header already present' do
  61. app = lambda { |env|
  62. [200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
  63. }
  64. status, headers, body = chunked(app).call(@env)
  65. status.should.equal 200
  66. headers['Transfer-Encoding'].should.equal 'identity'
  67. body.join.should.equal 'Hello World!'
  68. end
  69. [100, 204, 205, 304].each do |status_code|
  70. should "not modify response when status code is #{status_code}" do
  71. app = lambda { |env| [status_code, {}, []] }
  72. status, headers, _ = chunked(app).call(@env)
  73. status.should.equal status_code
  74. headers.should.not.include 'Transfer-Encoding'
  75. end
  76. end
  77. end