diff options
author | Jeremy Evans <code@jeremyevans.net> | 2022-02-18 15:38:50 -0800 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2022-02-18 15:47:40 -0800 |
commit | 472e12f5b6505cc2fdd3b5e529b616b3a2d5fbf8 (patch) | |
tree | c6cd5c94254b9c31502794e475c1e706a429eb16 /test | |
parent | 4e2c54187e6d2d989d50ce249199862ace42ecfc (diff) | |
download | rack-472e12f5b6505cc2fdd3b5e529b616b3a2d5fbf8.tar.gz |
Change SPEC to not allow uppercase header keys
Also, update CHANGELOG with other spec changes made since 2.2.
Implements #1592
Diffstat (limited to 'test')
34 files changed, 506 insertions, 657 deletions
diff --git a/test/helper.rb b/test/helper.rb index 83f7d0d6..fe1fa594 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -26,5 +26,19 @@ else def self.separate_testing end end + require 'minitest/global_expectations/autorun' require 'stringio' + +class Minitest::Spec + def self.deprecated(*args, &block) + it(*args) do + begin + verbose, $VERBOSE = $VERBOSE, nil + instance_exec(&block) + ensure + $VERBOSE = verbose + end + end + end +end diff --git a/test/spec_auth_basic.rb b/test/spec_auth_basic.rb index 5373897c..f1b09c88 100644 --- a/test/spec_auth_basic.rb +++ b/test/spec_auth_basic.rb @@ -15,7 +15,7 @@ describe Rack::Auth::Basic do def unprotected_app Rack::Lint.new lambda { |env| - [ 200, { 'Content-Type' => 'text/plain' }, ["Hi #{env['REMOTE_USER']}"] ] + [ 200, { 'content-type' => 'text/plain' }, ["Hi #{env['REMOTE_USER']}"] ] } end @@ -40,8 +40,8 @@ describe Rack::Auth::Basic do def assert_basic_auth_challenge(response) response.must_be :client_error? response.status.must_equal 401 - response.must_include 'WWW-Authenticate' - response.headers['WWW-Authenticate'].must_match(/Basic realm="#{Regexp.escape(realm)}"/) + response.must_include 'www-authenticate' + response.headers['www-authenticate'].must_match(/Basic realm="#{Regexp.escape(realm)}"/) response.body.must_be :empty? end @@ -68,7 +68,7 @@ describe Rack::Auth::Basic do request 'HTTP_AUTHORIZATION' => 'Digest params' do |response| response.must_be :client_error? response.status.must_equal 400 - response.wont_include 'WWW-Authenticate' + response.wont_include 'www-authenticate' end end @@ -76,7 +76,7 @@ describe Rack::Auth::Basic do request 'HTTP_AUTHORIZATION' => '' do |response| response.must_be :client_error? response.status.must_equal 400 - response.wont_include 'WWW-Authenticate' + response.wont_include 'www-authenticate' end end @@ -92,7 +92,7 @@ describe Rack::Auth::Basic do request 'HTTP_AUTHORIZATION' => auth do |response| response.must_be :client_error? response.status.must_equal 400 - response.wont_include 'WWW-Authenticate' + response.wont_include 'www-authenticate' end end diff --git a/test/spec_auth_digest.rb b/test/spec_auth_digest.rb index 6ed1f21e..e428375c 100644 --- a/test/spec_auth_digest.rb +++ b/test/spec_auth_digest.rb @@ -20,7 +20,7 @@ describe Rack::Auth::Digest::MD5 do def unprotected_app Rack::Lint.new lambda { |env| friend = Rack::Utils.parse_query(env["QUERY_STRING"])["friend"] - [ 200, { 'Content-Type' => 'text/plain' }, ["Hi #{env['REMOTE_USER']}#{friend ? " and #{friend}" : ''}"] ] + [ 200, { 'content-type' => 'text/plain' }, ["Hi #{env['REMOTE_USER']}#{friend ? " and #{friend}" : ''}"] ] } end @@ -91,7 +91,7 @@ describe Rack::Auth::Digest::MD5 do sleep wait end - challenge = response['WWW-Authenticate'].split(' ', 2).last + challenge = response['www-authenticate'].split(' ', 2).last params = Rack::Auth::Digest::Params.parse(challenge) @@ -112,15 +112,15 @@ describe Rack::Auth::Digest::MD5 do def assert_digest_auth_challenge(response) response.must_be :client_error? response.status.must_equal 401 - response.must_include 'WWW-Authenticate' - response.headers['WWW-Authenticate'].must_match(/^Digest /) + response.must_include 'www-authenticate' + response.headers['www-authenticate'].must_match(/^Digest /) response.body.must_be :empty? end def assert_bad_request(response) response.must_be :client_error? response.status.must_equal 400 - response.wont_include 'WWW-Authenticate' + response.wont_include 'www-authenticate' end it 'challenge when no credentials are specified' do @@ -170,7 +170,7 @@ describe Rack::Auth::Digest::MD5 do request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', wait: 1 do |response| response.status.must_equal 200 response.body.to_s.must_equal 'Hi Alice' - response.headers['WWW-Authenticate'].wont_match(/\bstale=true\b/) + response.headers['www-authenticate'].wont_match(/\bstale=true\b/) end ensure Rack::Auth::Digest::Nonce.time_limit = nil @@ -183,7 +183,7 @@ describe Rack::Auth::Digest::MD5 do request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', wait: 2 do |response| assert_digest_auth_challenge response - response.headers['WWW-Authenticate'].must_match(/\bstale=true\b/) + response.headers['www-authenticate'].must_match(/\bstale=true\b/) end ensure Rack::Auth::Digest::Nonce.time_limit = nil diff --git a/test/spec_builder.rb b/test/spec_builder.rb index 078c0f08..eda2d96f 100644 --- a/test/spec_builder.rb +++ b/test/spec_builder.rb @@ -37,10 +37,10 @@ describe Rack::Builder do it "supports mapping" do app = builder_to_app do map '/' do |outer_env| - run lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, ['root']] } + run lambda { |inner_env| [200, { "content-type" => "text/plain" }, ['root']] } end map '/sub' do - run lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, ['sub']] } + run lambda { |inner_env| [200, { "content-type" => "text/plain" }, ['sub']] } end end Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'root' @@ -51,13 +51,13 @@ describe Rack::Builder do app = builder_to_app do map '/sub' do use Rack::ContentLength - run lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, ['sub']] } + run lambda { |inner_env| [200, { "content-type" => "text/plain" }, ['sub']] } end use Rack::ContentLength - run lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, ['root']] } + run lambda { |inner_env| [200, { "content-type" => "text/plain" }, ['root']] } end - Rack::MockRequest.new(app).get("/").headers['Content-Length'].must_equal '4' - Rack::MockRequest.new(app).get("/sub").headers['Content-Length'].must_equal '3' + Rack::MockRequest.new(app).get("/").headers['content-length'].must_equal '4' + Rack::MockRequest.new(app).get("/sub").headers['content-length'].must_equal '3' end it "doesn't dupe env even when mapping" do @@ -66,7 +66,7 @@ describe Rack::Builder do map '/' do |outer_env| run lambda { |inner_env| inner_env['new_key'] = 'new_value' - [200, { "Content-Type" => "text/plain" }, ['root']] + [200, { "content-type" => "text/plain" }, ['root']] } end end @@ -77,7 +77,7 @@ describe Rack::Builder do it "dupe #to_app when mapping so Rack::Reloader can reload the application on each request" do app = builder do map '/' do |outer_env| - run lambda { |env| [200, { "Content-Type" => "text/plain" }, [object_id.to_s]] } + run lambda { |env| [200, { "content-type" => "text/plain" }, [object_id.to_s]] } end end @@ -116,7 +116,7 @@ describe Rack::Builder do 'secret' == password end - run lambda { |env| [200, { "Content-Type" => "text/plain" }, ['Hi Boss']] } + run lambda { |env| [200, { "content-type" => "text/plain" }, ['Hi Boss']] } end response = Rack::MockRequest.new(app).get("/") @@ -144,9 +144,9 @@ describe Rack::Builder do it "can mix map and run for endpoints" do app = builder do map '/sub' do - run lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, ['sub']] } + run lambda { |inner_env| [200, { "content-type" => "text/plain" }, ['sub']] } end - run lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, ['root']] } + run lambda { |inner_env| [200, { "content-type" => "text/plain" }, ['root']] } end Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'root' @@ -183,7 +183,7 @@ describe Rack::Builder do def call(env) raise "bzzzt" if @called > 0 @called += 1 - [200, { 'Content-Type' => 'text/plain' }, ['OK']] + [200, { 'content-type' => 'text/plain' }, ['OK']] end end @@ -283,7 +283,7 @@ describe Rack::Builder do describe 'new_from_string' do it "builds a rack app from string" do - app, = Rack::Builder.new_from_string "run lambda{|env| [200, {'Content-Type' => 'text/plane'}, ['OK']] }" + app, = Rack::Builder.new_from_string "run lambda{|env| [200, {'content-type' => 'text/plane'}, ['OK']] }" Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'OK' end end diff --git a/test/spec_cascade.rb b/test/spec_cascade.rb index b2529e0e..adafdb13 100644 --- a/test/spec_cascade.rb +++ b/test/spec_cascade.rb @@ -21,7 +21,7 @@ describe Rack::Cascade do app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" }) app3 = Rack::URLMap.new("/foo" => lambda { |env| - [200, { "Content-Type" => "text/plain" }, [""]]}) + [200, { "content-type" => "text/plain" }, [""]]}) it "dispatch onward on 404 and 405 by default" do cascade = cascade([app1, app2, app3]) @@ -55,17 +55,17 @@ describe Rack::Cascade do res = app.call('/') s, h, body = res s.must_equal 404 - h['Content-Type'].must_equal 'text/plain' + h['content-type'].must_equal 'text/plain' body.must_be_empty res[0] = 200 - h['Content-Type'] = 'text/html' + h['content-type'] = 'text/html' body << "a" res = app.call('/') s, h, body = res s.must_equal 404 - h['Content-Type'].must_equal 'text/plain' + h['content-type'].must_equal 'text/plain' body.must_be_empty end diff --git a/test/spec_chunked.rb b/test/spec_chunked.rb index 2c537001..18aad61d 100644 --- a/test/spec_chunked.rb +++ b/test/spec_chunked.rb @@ -36,27 +36,27 @@ describe Rack::Chunked do it 'yields trailer headers after the response' do app = lambda { |env| - [200, { "Content-Type" => "text/plain", "Trailer" => "Expires" }, TrailerBody.new] + [200, { "content-type" => "text/plain", "trailer" => "Expires" }, TrailerBody.new] } response = Rack::MockResponse.new(*chunked(app).call(@env)) - response.headers.wont_include 'Content-Length' - response.headers['Transfer-Encoding'].must_equal 'chunked' + response.headers.wont_include 'content-length' + response.headers['transfer-encoding'].must_equal 'chunked' response.body.must_equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\nExpires: tomorrow\r\n\r\n" end - it 'chunk responses with no Content-Length' do - app = lambda { |env| [200, { "Content-Type" => "text/plain" }, ['Hello', ' ', 'World!']] } + it 'chunk responses with no content-length' do + app = lambda { |env| [200, { "content-type" => "text/plain" }, ['Hello', ' ', 'World!']] } response = Rack::MockResponse.new(*chunked(app).call(@env)) - response.headers.wont_include 'Content-Length' - response.headers['Transfer-Encoding'].must_equal 'chunked' + response.headers.wont_include 'content-length' + response.headers['transfer-encoding'].must_equal 'chunked' response.body.must_equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n" end it 'chunks empty bodies properly' do - app = lambda { |env| [200, { "Content-Type" => "text/plain" }, []] } + app = lambda { |env| [200, { "content-type" => "text/plain" }, []] } response = Rack::MockResponse.new(*chunked(app).call(@env)) - response.headers.wont_include 'Content-Length' - response.headers['Transfer-Encoding'].must_equal 'chunked' + response.headers.wont_include 'content-length' + response.headers['transfer-encoding'].must_equal 'chunked' response.body.must_equal "0\r\n\r\n" end @@ -65,51 +65,51 @@ describe Rack::Chunked do closed = false def obj.each; yield 's' end obj.define_singleton_method(:close) { closed = true } - app = lambda { |env| [200, { "Content-Type" => "text/plain" }, obj] } + app = lambda { |env| [200, { "content-type" => "text/plain" }, obj] } response = Rack::MockRequest.new(Rack::Chunked.new(app)).get('/', @env) - response.headers.wont_include 'Content-Length' - response.headers['Transfer-Encoding'].must_equal 'chunked' + response.headers.wont_include 'content-length' + response.headers['transfer-encoding'].must_equal 'chunked' response.body.must_equal "1\r\ns\r\n0\r\n\r\n" closed.must_equal true end it 'chunks encoded bodies properly' do body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") } - app = lambda { |env| [200, { "Content-Type" => "text/plain" }, body] } + app = lambda { |env| [200, { "content-type" => "text/plain" }, body] } response = Rack::MockResponse.new(*chunked(app).call(@env)) - response.headers.wont_include 'Content-Length' - response.headers['Transfer-Encoding'].must_equal 'chunked' + response.headers.wont_include 'content-length' + response.headers['transfer-encoding'].must_equal 'chunked' response.body.encoding.to_s.must_equal "ASCII-8BIT" response.body.must_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".dup.force_encoding("BINARY") response.body.must_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".dup.force_encoding(Encoding::BINARY) end - it 'not modify response when Content-Length header present' do + it 'not modify response when content-length header present' do app = lambda { |env| - [200, { "Content-Type" => "text/plain", 'Content-Length' => '12' }, ['Hello', ' ', 'World!']] + [200, { "content-type" => "text/plain", 'content-length' => '12' }, ['Hello', ' ', 'World!']] } status, headers, body = chunked(app).call(@env) status.must_equal 200 - headers.wont_include 'Transfer-Encoding' - headers.must_include 'Content-Length' + headers.wont_include 'transfer-encoding' + headers.must_include 'content-length' body.join.must_equal 'Hello World!' end it 'not modify response when client is HTTP/1.0' do - app = lambda { |env| [200, { "Content-Type" => "text/plain" }, ['Hello', ' ', 'World!']] } + app = lambda { |env| [200, { "content-type" => "text/plain" }, ['Hello', ' ', 'World!']] } @env['SERVER_PROTOCOL'] = 'HTTP/1.0' status, headers, body = chunked(app).call(@env) status.must_equal 200 - headers.wont_include 'Transfer-Encoding' + headers.wont_include 'transfer-encoding' body.join.must_equal 'Hello World!' end it 'not modify response when client is ancient, pre-HTTP/1.0' do - app = lambda { |env| [200, { "Content-Type" => "text/plain" }, ['Hello', ' ', 'World!']] } + app = lambda { |env| [200, { "content-type" => "text/plain" }, ['Hello', ' ', 'World!']] } check = lambda do status, headers, body = chunked(app).call(@env.dup) status.must_equal 200 - headers.wont_include 'Transfer-Encoding' + headers.wont_include 'transfer-encoding' body.join.must_equal 'Hello World!' end @@ -120,13 +120,13 @@ describe Rack::Chunked do check.call end - it 'not modify response when Transfer-Encoding header already present' do + it 'not modify response when transfer-encoding header already present' do app = lambda { |env| - [200, { "Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity' }, ['Hello', ' ', 'World!']] + [200, { "content-type" => "text/plain", 'transfer-encoding' => 'identity' }, ['Hello', ' ', 'World!']] } status, headers, body = chunked(app).call(@env) status.must_equal 200 - headers['Transfer-Encoding'].must_equal 'identity' + headers['transfer-encoding'].must_equal 'identity' body.join.must_equal 'Hello World!' end @@ -135,7 +135,7 @@ describe Rack::Chunked do app = lambda { |env| [status_code, {}, []] } status, headers, _ = chunked(app).call(@env) status.must_equal status_code - headers.wont_include 'Transfer-Encoding' + headers.wont_include 'transfer-encoding' end end end diff --git a/test/spec_common_logger.rb b/test/spec_common_logger.rb index 8a572cbb..60db7704 100644 --- a/test/spec_common_logger.rb +++ b/test/spec_common_logger.rb @@ -15,15 +15,15 @@ describe Rack::CommonLogger do app = Rack::Lint.new lambda { |env| [200, - { "Content-Type" => "text/html", "Content-Length" => length.to_s }, + { "content-type" => "text/html", "content-length" => length.to_s }, [obj]]} app_without_length = Rack::Lint.new lambda { |env| [200, - { "Content-Type" => "text/html" }, + { "content-type" => "text/html" }, []]} app_with_zero_length = Rack::Lint.new lambda { |env| [200, - { "Content-Type" => "text/html", "Content-Length" => "0" }, + { "content-type" => "text/html", "content-length" => "0" }, []]} it "log to rack.errors by default" do diff --git a/test/spec_conditional_get.rb b/test/spec_conditional_get.rb index 6ab69721..3aeae162 100644 --- a/test/spec_conditional_get.rb +++ b/test/spec_conditional_get.rb @@ -17,7 +17,7 @@ describe Rack::ConditionalGet do it "set a 304 status and truncate body when If-Modified-Since hits" do timestamp = Time.now.httpdate app = conditional_get(lambda { |env| - [200, { 'Last-Modified' => timestamp }, ['TEST']] }) + [200, { 'last-modified' => timestamp }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp) @@ -28,7 +28,7 @@ describe Rack::ConditionalGet do it "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do app = conditional_get(lambda { |env| - [200, { 'Last-Modified' => (Time.now - 3600).httpdate }, ['TEST']] }) + [200, { 'last-modified' => (Time.now - 3600).httpdate }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate) @@ -39,7 +39,7 @@ describe Rack::ConditionalGet do it "set a 304 status and truncate body when If-None-Match hits" do app = conditional_get(lambda { |env| - [200, { 'ETag' => '1234' }, ['TEST']] }) + [200, { 'etag' => '1234' }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_NONE_MATCH' => '1234') @@ -48,9 +48,9 @@ describe Rack::ConditionalGet do response.body.must_be :empty? end - it "set a 304 status and truncate body when If-None-Match hits but If-Modified-Since is after Last-Modified" do + it "set a 304 status and truncate body when If-None-Match hits but If-Modified-Since is after last-modified" do app = conditional_get(lambda { |env| - [200, { 'Last-Modified' => (Time.now + 3600).httpdate, 'Etag' => '1234', 'Content-Type' => 'text/plain' }, ['TEST']] }) + [200, { 'last-modified' => (Time.now + 3600).httpdate, 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate, 'HTTP_IF_NONE_MATCH' => '1234') @@ -59,10 +59,10 @@ describe Rack::ConditionalGet do response.body.must_be :empty? end - it "not set a 304 status if If-Modified-Since hits but Etag does not" do + it "not set a 304 status if If-Modified-Since hits but etag does not" do timestamp = Time.now.httpdate app = conditional_get(lambda { |env| - [200, { 'Last-Modified' => timestamp, 'Etag' => '1234', 'Content-Type' => 'text/plain' }, ['TEST']] }) + [200, { 'last-modified' => timestamp, 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321') @@ -74,7 +74,7 @@ describe Rack::ConditionalGet do it "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do timestamp = Time.now.httpdate app = conditional_get(lambda { |env| - [200, { 'Last-Modified' => timestamp, 'ETag' => '1234' }, ['TEST']] }) + [200, { 'last-modified' => timestamp, 'etag' => '1234' }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234') @@ -85,7 +85,7 @@ describe Rack::ConditionalGet do it "not affect non-GET/HEAD requests" do app = conditional_get(lambda { |env| - [200, { 'Etag' => '1234', 'Content-Type' => 'text/plain' }, ['TEST']] }) + [200, { 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] }) response = Rack::MockRequest.new(app). post("/", 'HTTP_IF_NONE_MATCH' => '1234') @@ -96,7 +96,7 @@ describe Rack::ConditionalGet do it "not affect non-200 requests" do app = conditional_get(lambda { |env| - [302, { 'Etag' => '1234', 'Content-Type' => 'text/plain' }, ['TEST']] }) + [302, { 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_NONE_MATCH' => '1234') @@ -108,7 +108,7 @@ describe Rack::ConditionalGet do it "not affect requests with malformed HTTP_IF_NONE_MATCH" do bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z') app = conditional_get(lambda { |env| - [200, { 'Last-Modified' => (Time.now - 3600).httpdate, 'Content-Type' => 'text/plain' }, ['TEST']] }) + [200, { 'last-modified' => (Time.now - 3600).httpdate, 'content-type' => 'text/plain' }, ['TEST']] }) response = Rack::MockRequest.new(app). get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp) diff --git a/test/spec_config.rb b/test/spec_config.rb index 531077d1..8ef28965 100644 --- a/test/spec_config.rb +++ b/test/spec_config.rb @@ -17,7 +17,7 @@ describe Rack::Config do env['greeting'] = 'hello' end run lambda { |env| - [200, { 'Content-Type' => 'text/plain' }, [env['greeting'] || '']] + [200, { 'content-type' => 'text/plain' }, [env['greeting'] || '']] } end diff --git a/test/spec_content_length.rb b/test/spec_content_length.rb index a3a5995c..8f7bba9c 100644 --- a/test/spec_content_length.rb +++ b/test/spec_content_length.rb @@ -17,46 +17,46 @@ describe Rack::ContentLength do Rack::MockRequest.env_for end - it "set Content-Length on Array bodies if none is set" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] } + it "set content-length on Array bodies if none is set" do + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } response = content_length(app).call(request) - response[1]['Content-Length'].must_equal '13' + response[1]['content-length'].must_equal '13' end - it "not set Content-Length on variable length bodies" do + it "not set content-length on variable length bodies" do body = lambda { "Hello World!" } def body.each ; yield call ; end - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, body] } + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, body] } response = content_length(app).call(request) - response[1]['Content-Length'].must_be_nil + response[1]['content-length'].must_be_nil end - it "not change Content-Length if it is already set" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain', 'Content-Length' => '1' }, "Hello, World!"] } + it "not change content-length if it is already set" do + app = lambda { |env| [200, { 'content-type' => 'text/plain', 'content-length' => '1' }, "Hello, World!"] } response = content_length(app).call(request) - response[1]['Content-Length'].must_equal '1' + response[1]['content-length'].must_equal '1' end - it "not set Content-Length on 304 responses" do + it "not set content-length on 304 responses" do app = lambda { |env| [304, {}, []] } response = content_length(app).call(request) - response[1]['Content-Length'].must_be_nil + response[1]['content-length'].must_be_nil end - it "not set Content-Length when Transfer-Encoding is chunked" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked' }, []] } + it "not set content-length when transfer-encoding is chunked" do + app = lambda { |env| [200, { 'content-type' => 'text/plain', 'transfer-encoding' => 'chunked' }, []] } response = content_length(app).call(request) - response[1]['Content-Length'].must_be_nil + response[1]['content-length'].must_be_nil end # Using "Connection: close" for this is fairly contended. It might be useful # to have some other way to signal this. # - # should "not force a Content-Length when Connection:close" do + # should "not force a content-length when Connection:close" do # app = lambda { |env| [200, {'Connection' => 'close'}, []] } # response = content_length(app).call({}) - # response[1]['Content-Length'].must_be_nil + # response[1]['content-length'].must_be_nil # end it "close bodies that need to be closed" do @@ -67,7 +67,7 @@ describe Rack::ContentLength do def to_ary; enum_for.to_a; end end.new(%w[one two three]) - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, body] } + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, body] } content_length(app).call(request) body.closed.must_equal true end @@ -80,10 +80,10 @@ describe Rack::ContentLength do def to_ary; enum_for.to_a; end end.new(%w[one two three]) - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, body] } + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, body] } response = content_length(app).call(request) expected = %w[one two three] - response[1]['Content-Length'].must_equal expected.join.size.to_s + response[1]['content-length'].must_equal expected.join.size.to_s response[2].to_enum.to_a.must_equal expected end end diff --git a/test/spec_content_type.rb b/test/spec_content_type.rb index 93006b06..4808376a 100644 --- a/test/spec_content_type.rb +++ b/test/spec_content_type.rb @@ -17,37 +17,30 @@ describe Rack::ContentType do Rack::MockRequest.env_for end - it "set Content-Type to default text/html if none is set" do + it "set content-type to default text/html if none is set" do app = lambda { |env| [200, {}, "Hello, World!"] } headers = content_type(app).call(request)[1] - headers['Content-Type'].must_equal 'text/html' + headers['content-type'].must_equal 'text/html' end - it "set Content-Type to chosen default if none is set" do + it "set content-type to chosen default if none is set" do app = lambda { |env| [200, {}, "Hello, World!"] } headers = content_type(app, 'application/octet-stream').call(request)[1] - headers['Content-Type'].must_equal 'application/octet-stream' + headers['content-type'].must_equal 'application/octet-stream' end - it "not change Content-Type if it is already set" do - app = lambda { |env| [200, { 'Content-Type' => 'foo/bar' }, "Hello, World!"] } + it "not change content-type if it is already set" do + app = lambda { |env| [200, { 'content-type' => 'foo/bar' }, "Hello, World!"] } headers = content_type(app).call(request)[1] - headers['Content-Type'].must_equal 'foo/bar' - end - - it "detect Content-Type case insensitive" do - app = lambda { |env| [200, { 'CONTENT-Type' => 'foo/bar' }, "Hello, World!"] } - headers = content_type(app).call(request)[1] - headers.to_a.select { |k, v| k.downcase == "content-type" }. - must_equal [["CONTENT-Type", "foo/bar"]] + headers['content-type'].must_equal 'foo/bar' end [100, 204, 304].each do |code| - it "not set Content-Type on #{code} responses" do + it "not set content-type on #{code} responses" do app = lambda { |env| [code, {}, []] } response = content_type(app, "text/html").call(request) - response[1]['Content-Type'].must_be_nil + response[1]['content-type'].must_be_nil end end end diff --git a/test/spec_deflater.rb b/test/spec_deflater.rb index 2eb60bd9..71436685 100644 --- a/test/spec_deflater.rb +++ b/test/spec_deflater.rb @@ -16,7 +16,7 @@ describe Rack::Deflater do body = [body] if body.respond_to? :to_str app = lambda do |env| res = [status, options['response_headers'] || {}, body] - res[1]['Content-Type'] = 'text/plain' unless res[0] == 304 + res[1]['content-type'] = 'text/plain' unless res[0] == 304 res end @@ -74,7 +74,7 @@ describe Rack::Deflater do io = StringIO.new(body_text) gz = Zlib::GzipReader.new(io) mtime = gz.mtime.to_i - if last_mod = headers['Last-Modified'] + if last_mod = headers['last-modified'] Time.httpdate(last_mod).to_i.must_equal mtime else mtime.must_be(:<=, Time.now.to_i) @@ -109,9 +109,9 @@ describe Rack::Deflater do verify(200, 'foobar', deflate_or_gzip, { 'app_body' => app_body }) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) end end @@ -122,9 +122,9 @@ describe Rack::Deflater do verify(200, 'foobar', deflate_or_gzip, { 'app_body' => app_body }) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) end end @@ -135,9 +135,9 @@ describe Rack::Deflater do verify(200, app_body, deflate_or_gzip, { 'skip_body_verify' => true }) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) buf = [] @@ -155,9 +155,9 @@ describe Rack::Deflater do opts = { 'skip_body_verify' => true } verify(200, app_body, 'gzip', opts) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) buf = [] @@ -179,9 +179,9 @@ describe Rack::Deflater do it 'be able to deflate String bodies' do verify(200, 'Hello world!', deflate_or_gzip) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) end end @@ -192,9 +192,9 @@ describe Rack::Deflater do verify(200, 'foobar', 'gzip', { 'app_body' => app_body }) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) end end @@ -205,9 +205,9 @@ describe Rack::Deflater do verify(200, app_body, 'gzip', { 'skip_body_verify' => true }) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) buf = [] @@ -222,8 +222,8 @@ describe Rack::Deflater do it 'be able to fallback to no deflation' do verify(200, 'Hello world!', 'superzip') do |status, headers, body| headers.must_equal({ - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) end end @@ -255,65 +255,65 @@ describe Rack::Deflater do verify(406, not_found_body1, 'identity;q=0', options1) do |status, headers, body| headers.must_equal({ - 'Content-Type' => 'text/plain', - 'Content-Length' => not_found_body1.length.to_s + 'content-type' => 'text/plain', + 'content-length' => not_found_body1.length.to_s }) end verify(406, not_found_body2, 'identity;q=0', options2) do |status, headers, body| headers.must_equal({ - 'Content-Type' => 'text/plain', - 'Content-Length' => not_found_body2.length.to_s + 'content-type' => 'text/plain', + 'content-length' => not_found_body2.length.to_s }) end end - it 'handle gzip response with Last-Modified header' do + it 'handle gzip response with last-modified header' do last_modified = Time.now.httpdate options = { 'response_headers' => { - 'Content-Type' => 'text/plain', - 'Last-Modified' => last_modified + 'content-type' => 'text/plain', + 'last-modified' => last_modified } } verify(200, 'Hello World!', 'gzip', options) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Last-Modified' => last_modified, - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'last-modified' => last_modified, + 'content-type' => 'text/plain' }) end end - it 'do nothing when no-transform Cache-Control directive present' do + it 'do nothing when no-transform cache-control directive present' do options = { 'response_headers' => { - 'Content-Type' => 'text/plain', - 'Cache-Control' => 'no-transform' + 'content-type' => 'text/plain', + 'cache-control' => 'no-transform' } } verify(200, 'Hello World!', { 'gzip' => nil }, options) do |status, headers, body| - headers.wont_include 'Content-Encoding' + headers.wont_include 'content-encoding' end end - it 'do nothing when Content-Encoding already present' do + it 'do nothing when content-encoding already present' do options = { 'response_headers' => { - 'Content-Type' => 'text/plain', - 'Content-Encoding' => 'gzip' + 'content-type' => 'text/plain', + 'content-encoding' => 'gzip' } } verify(200, 'Hello World!', { 'gzip' => nil }, options) end - it 'deflate when Content-Encoding is identity' do + it 'deflate when content-encoding is identity' do options = { 'response_headers' => { - 'Content-Type' => 'text/plain', - 'Content-Encoding' => 'identity' + 'content-type' => 'text/plain', + 'content-encoding' => 'identity' } } verify(200, 'Hello World!', deflate_or_gzip, options) @@ -322,7 +322,7 @@ describe Rack::Deflater do it "deflate if content-type matches :include" do options = { 'response_headers' => { - 'Content-Type' => 'text/plain' + 'content-type' => 'text/plain' }, 'deflater_options' => { include: %w(text/plain) @@ -334,7 +334,7 @@ describe Rack::Deflater do it "deflate if content-type is included it :include" do options = { 'response_headers' => { - 'Content-Type' => 'text/plain; charset=us-ascii' + 'content-type' => 'text/plain; charset=us-ascii' }, 'deflater_options' => { include: %w(text/plain) @@ -355,7 +355,7 @@ describe Rack::Deflater do it "not deflate if content-type do not match :include" do options = { 'response_headers' => { - 'Content-Type' => 'text/plain' + 'content-type' => 'text/plain' }, 'deflater_options' => { include: %w(text/json) @@ -367,7 +367,7 @@ describe Rack::Deflater do it "not deflate if content-length is 0" do options = { 'response_headers' => { - 'Content-Length' => '0' + 'content-length' => '0' }, } verify(200, '', { 'gzip' => nil }, options) @@ -391,16 +391,16 @@ describe Rack::Deflater do verify(200, 'Hello World!', { 'gzip' => nil }, options) end - it "check for Content-Length via :if" do + it "check for content-length via :if" do response = 'Hello World!' response_len = response.length options = { 'response_headers' => { - 'Content-Length' => response_len.to_s + 'content-length' => response_len.to_s }, 'deflater_options' => { if: lambda { |env, status, headers, body| - headers['Content-Length'].to_i >= response_len + headers['content-length'].to_i >= response_len } } } @@ -423,9 +423,9 @@ describe Rack::Deflater do } verify(200, app_body, deflate_or_gzip, options) do |status, headers, body| headers.must_equal({ - 'Content-Encoding' => 'gzip', - 'Vary' => 'Accept-Encoding', - 'Content-Type' => 'text/plain' + 'content-encoding' => 'gzip', + 'vary' => 'Accept-Encoding', + 'content-type' => 'text/plain' }) buf = ''.dup diff --git a/test/spec_directory.rb b/test/spec_directory.rb index 9e46e896..d7e90333 100644 --- a/test/spec_directory.rb +++ b/test/spec_directory.rb @@ -14,7 +14,7 @@ end describe Rack::Directory do DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT - FILE_CATCH = proc{|env| [200, { 'Content-Type' => 'text/plain', "Content-Length" => "7" }, ['passed!']] } + FILE_CATCH = proc{|env| [200, { 'content-type' => 'text/plain', "content-length" => "7" }, ['passed!']] } attr_reader :app diff --git a/test/spec_etag.rb b/test/spec_etag.rb index 09c5636c..568bdc60 100644 --- a/test/spec_etag.rb +++ b/test/spec_etag.rb @@ -23,81 +23,81 @@ describe Rack::ETag do end it "set ETag if none is set if status is 200" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] } + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } response = etag(app).call(request) - response[1]['ETag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\"" + response[1]['etag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\"" end it "set ETag if none is set if status is 201" do - app = lambda { |env| [201, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] } + app = lambda { |env| [201, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } response = etag(app).call(request) - response[1]['ETag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\"" + response[1]['etag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\"" end - it "set Cache-Control to 'max-age=0, private, must-revalidate' (default) if none is set" do - app = lambda { |env| [201, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] } + it "set cache-control to 'max-age=0, private, must-revalidate' (default) if none is set" do + app = lambda { |env| [201, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } response = etag(app).call(request) - response[1]['Cache-Control'].must_equal 'max-age=0, private, must-revalidate' + response[1]['cache-control'].must_equal 'max-age=0, private, must-revalidate' end - it "set Cache-Control to chosen one if none is set" do - app = lambda { |env| [201, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] } + it "set cache-control to chosen one if none is set" do + app = lambda { |env| [201, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } response = etag(app, nil, 'public').call(request) - response[1]['Cache-Control'].must_equal 'public' + response[1]['cache-control'].must_equal 'public' end - it "set a given Cache-Control even if digest could not be calculated" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + it "set a given cache-control even if digest could not be calculated" do + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, []] } response = etag(app, 'no-cache').call(request) - response[1]['Cache-Control'].must_equal 'no-cache' + response[1]['cache-control'].must_equal 'no-cache' end - it "not set Cache-Control if it is already set" do - app = lambda { |env| [201, { 'Content-Type' => 'text/plain', 'Cache-Control' => 'public' }, ["Hello, World!"]] } + it "not set cache-control if it is already set" do + app = lambda { |env| [201, { 'content-type' => 'text/plain', 'cache-control' => 'public' }, ["Hello, World!"]] } response = etag(app).call(request) - response[1]['Cache-Control'].must_equal 'public' + response[1]['cache-control'].must_equal 'public' end - it "not set Cache-Control if directive isn't present" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] } + it "not set cache-control if directive isn't present" do + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } response = etag(app, nil, nil).call(request) - response[1]['Cache-Control'].must_be_nil + response[1]['cache-control'].must_be_nil end it "not change ETag if it is already set" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain', 'ETag' => '"abc"' }, ["Hello, World!"]] } + app = lambda { |env| [200, { 'content-type' => 'text/plain', 'etag' => '"abc"' }, ["Hello, World!"]] } response = etag(app).call(request) - response[1]['ETag'].must_equal "\"abc\"" + response[1]['etag'].must_equal "\"abc\"" end it "not set ETag if body is empty" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate }, []] } + app = lambda { |env| [200, { 'content-type' => 'text/plain', 'last-modified' => Time.now.httpdate }, []] } response = etag(app).call(request) - response[1]['ETag'].must_be_nil + response[1]['etag'].must_be_nil end - it "not set ETag if Last-Modified is set" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain', 'Last-Modified' => Time.now.httpdate }, ["Hello, World!"]] } + it "not set ETag if last-modified is set" do + app = lambda { |env| [200, { 'content-type' => 'text/plain', 'last-modified' => Time.now.httpdate }, ["Hello, World!"]] } response = etag(app).call(request) - response[1]['ETag'].must_be_nil + response[1]['etag'].must_be_nil end it "not set ETag if a sendfile_body is given" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, sendfile_body] } + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, sendfile_body] } response = etag(app).call(request) - response[1]['ETag'].must_be_nil + response[1]['etag'].must_be_nil end it "not set ETag if a status is not 200 or 201" do - app = lambda { |env| [401, { 'Content-Type' => 'text/plain' }, ['Access denied.']] } + app = lambda { |env| [401, { 'content-type' => 'text/plain' }, ['Access denied.']] } response = etag(app).call(request) - response[1]['ETag'].must_be_nil + response[1]['etag'].must_be_nil end it "set ETag even if no-cache is given" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain', 'Cache-Control' => 'no-cache, must-revalidate' }, ['Hello, World!']] } + app = lambda { |env| [200, { 'content-type' => 'text/plain', 'cache-control' => 'no-cache, must-revalidate' }, ['Hello, World!']] } response = etag(app).call(request) - response[1]['ETag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\"" + response[1]['etag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\"" end it "close the original body" do diff --git a/test/spec_files.rb b/test/spec_files.rb index 5dfb8c6e..bff436ee 100644 --- a/test/spec_files.rb +++ b/test/spec_files.rb @@ -64,13 +64,13 @@ describe Rack::Files do res.status.must_equal 404 end - it "set Last-Modified header" do + it "set last-modified header" do res = Rack::MockRequest.new(files(DOCROOT)).get("/cgi/test") path = File.join(DOCROOT, "/cgi/test") res.must_be :ok? - res["Last-Modified"].must_equal File.mtime(path).httpdate + res["last-modified"].must_equal File.mtime(path).httpdate end it "return 304 if file isn't modified since last serve" do @@ -196,8 +196,8 @@ describe Rack::Files do res = Rack::MockResponse.new(*files(DOCROOT).call(env)) res.status.must_equal 206 - res["Content-Length"].must_equal "12" - res["Content-Range"].must_equal "bytes 22-33/209" + res["content-length"].must_equal "12" + res["content-range"].must_equal "bytes 22-33/209" res.body.must_equal "IS FILE! ***" end @@ -207,18 +207,18 @@ describe Rack::Files do res = Rack::MockResponse.new(*files(DOCROOT).call(env)) res.status.must_equal 206 - res["Content-Length"].must_equal "191" - res["Content-Type"].must_equal "multipart/byteranges; boundary=AaB03x" + res["content-length"].must_equal "191" + res["content-type"].must_equal "multipart/byteranges; boundary=AaB03x" expected_body = <<-EOF \r --AaB03x\r -Content-Type: text/plain\r -Content-Range: bytes 22-33/209\r +content-type: text/plain\r +content-range: bytes 22-33/209\r \r IS FILE! ***\r --AaB03x\r -Content-Type: text/plain\r -Content-Range: bytes 60-80/209\r +content-type: text/plain\r +content-range: bytes 60-80/209\r \r , tests will break!!!\r --AaB03x--\r @@ -233,17 +233,17 @@ Content-Range: bytes 60-80/209\r res = Rack::MockResponse.new(*files(DOCROOT).call(env)) res.status.must_equal 416 - res["Content-Range"].must_equal "bytes */209" + res["content-range"].must_equal "bytes */209" end it "support custom http headers" do env = Rack::MockRequest.env_for("/cgi/test") - status, heads, _ = files(DOCROOT, 'Cache-Control' => 'public, max-age=38', - 'Access-Control-Allow-Origin' => '*').call(env) + status, heads, _ = files(DOCROOT, 'cache-control' => 'public, max-age=38', + 'access-control-allow-origin' => '*').call(env) status.must_equal 200 - heads['Cache-Control'].must_equal 'public, max-age=38' - heads['Access-Control-Allow-Origin'].must_equal '*' + heads['cache-control'].must_equal 'public, max-age=38' + heads['access-control-allow-origin'].must_equal '*' end it "support not add custom http headers if none are supplied" do @@ -251,7 +251,7 @@ Content-Range: bytes 60-80/209\r status, heads, _ = files(DOCROOT).call(env) status.must_equal 200 - heads['Cache-Control'].must_be_nil + heads['cache-control'].must_be_nil heads['Access-Control-Allow-Origin'].must_be_nil end @@ -263,7 +263,7 @@ Content-Range: bytes 60-80/209\r res = req.send(method, "/cgi/test") res.must_be :client_error? res.must_be :method_not_allowed? - res.headers['Allow'].split(/, */).sort.must_equal %w(GET HEAD OPTIONS) + res.headers['allow'].split(/, */).sort.must_equal %w(GET HEAD OPTIONS) end allowed = %w[get head options] @@ -277,36 +277,36 @@ Content-Range: bytes 60-80/209\r req = Rack::MockRequest.new(files(DOCROOT)) res = req.options('/cgi/test') res.must_be :successful? - res.headers['Allow'].wont_equal nil - res.headers['Allow'].split(/, */).sort.must_equal %w(GET HEAD OPTIONS) + res.headers['allow'].wont_equal nil + res.headers['allow'].split(/, */).sort.must_equal %w(GET HEAD OPTIONS) end - it "set Content-Length correctly for HEAD requests" do + it "set content-length correctly for HEAD requests" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))) res = req.head "/cgi/test" res.must_be :successful? - res['Content-Length'].must_equal "209" + res['content-length'].must_equal "209" end it "default to a mime type of text/plain" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT))) res = req.get "/cgi/test" res.must_be :successful? - res['Content-Type'].must_equal "text/plain" + res['content-type'].must_equal "text/plain" end it "allow the default mime type to be set" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT, nil, 'application/octet-stream'))) res = req.get "/cgi/test" res.must_be :successful? - res['Content-Type'].must_equal "application/octet-stream" + res['content-type'].must_equal "application/octet-stream" end - it "not set Content-Type if the mime type is not set" do + it "not set content-type if the mime type is not set" do req = Rack::MockRequest.new(Rack::Lint.new(Rack::Files.new(DOCROOT, nil, nil))) res = req.get "/cgi/test" res.must_be :successful? - res['Content-Type'].must_be_nil + res['content-type'].must_be_nil end it "return error when file not found for head request" do diff --git a/test/spec_head.rb b/test/spec_head.rb index 0f0eb0c3..d09eb8f9 100644 --- a/test/spec_head.rb +++ b/test/spec_head.rb @@ -13,7 +13,7 @@ describe Rack::Head do def test_response(headers = {}) body = StringIO.new "foo" app = lambda do |env| - [200, { "Content-type" => "test/plain", "Content-length" => "3" }, body] + [200, { "content-type" => "test/plain", "content-length" => "3" }, body] end request = Rack::MockRequest.env_for("/", headers) response = Rack::Lint.new(Rack::Head.new(app)).call(request) @@ -26,7 +26,7 @@ describe Rack::Head do resp, _ = test_response("REQUEST_METHOD" => type) resp[0].must_equal 200 - resp[1].must_equal "Content-type" => "test/plain", "Content-length" => "3" + resp[1].must_equal "content-type" => "test/plain", "content-length" => "3" resp[2].to_enum.to_a.must_equal ["foo"] end end @@ -35,14 +35,14 @@ describe Rack::Head do resp, _ = test_response("REQUEST_METHOD" => "HEAD") resp[0].must_equal 200 - resp[1].must_equal "Content-type" => "test/plain", "Content-length" => "3" + resp[1].must_equal "content-type" => "test/plain", "content-length" => "3" resp[2].to_enum.to_a.must_equal [] end it "close the body when it is removed" do resp, body = test_response("REQUEST_METHOD" => "HEAD") resp[0].must_equal 200 - resp[1].must_equal "Content-type" => "test/plain", "Content-length" => "3" + resp[1].must_equal "content-type" => "test/plain", "content-length" => "3" resp[2].to_enum.to_a.must_equal [] body.wont_be :closed? resp[2].close diff --git a/test/spec_lint.rb b/test/spec_lint.rb index db0564a3..974ed262 100755 --- a/test/spec_lint.rb +++ b/test/spec_lint.rb @@ -15,7 +15,7 @@ describe Rack::Lint do it "pass valid request" do Rack::Lint.new(lambda { |env| - [200, { "Content-type" => "test/plain", "Content-length" => "3" }, ["foo"]] + [200, { "content-type" => "test/plain", "content-length" => "3" }, ["foo"]] }).call(env({})).first.must_equal 200 end @@ -317,17 +317,18 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| - [200, { "Status" => "404" }, []] + [200, { "status" => "404" }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). - message.must_match(/must not contain Status/) + message.must_match(/must not contain status/) # From RFC 7230:<F24><F25> # Most HTTP header field values are defined using common syntax # components (token, quoted-string, and comment) separated by # whitespace or specific delimiting characters. Delimiters are chosen # from the set of US-ASCII visual characters not allowed in a token - # (DQUOTE and "(),/:;<=>?@[\]{}"). + # (DQUOTE and "(),/:;<=>?@[\]{}"). Rack also doesn't allow uppercase + # ASCII (A-Z) in header keys. # # token = 1*tchar # @@ -344,7 +345,15 @@ describe Rack::Lint do }.must_raise(Rack::Lint::LintError, "on invalid header: #{invalid_header}"). message.must_equal("invalid header name: #{invalid_header}") end - valid_headers = 0.upto(127).map(&:chr) - invalid_headers + ('A'..'Z').each do |invalid_header| + lambda { + Rack::Lint.new(lambda { |env| + [200, { invalid_header => "text/plain" }, []] + }).call(env({})) + }.must_raise(Rack::Lint::LintError, "on invalid header: #{invalid_header}"). + message.must_equal("uppercase character in header name: #{invalid_header}") + end + valid_headers = 0.upto(127).map(&:chr) - invalid_headers - ('A'..'Z').to_a valid_headers.each do |valid_header| Rack::Lint.new(lambda { |env| [200, { valid_header => "text/plain" }, []] @@ -353,34 +362,34 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| - [200, { "Foo" => Object.new }, []] + [200, { "foo" => Object.new }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). - message.must_equal "a header value must be a String, but the value of 'Foo' is a Object" + message.must_equal "a header value must be a String, but the value of 'foo' is a Object" lambda { Rack::Lint.new(lambda { |env| - [200, { "Foo" => [1, 2, 3] }, []] + [200, { "foo" => [1, 2, 3] }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). - message.must_equal "a header value must be a String, but the value of 'Foo' is a Array" + message.must_equal "a header value must be a String, but the value of 'foo' is a Array" lambda { Rack::Lint.new(lambda { |env| - [200, { "Foo-Bar" => "text\000plain" }, []] + [200, { "foo-bar" => "text\000plain" }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). message.must_match(/invalid header/) # line ends (010).must_be :allowed in header values.? Rack::Lint.new(lambda { |env| - [200, { "Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []] + [200, { "foo-bar" => "one\ntwo\nthree", "content-length" => "0", "content-type" => "text/plain" }, []] }).call(env({})).first.must_equal 200 lambda { Rack::Lint.new(lambda { |env| - [200, [%w(Content-Type text/plain), %w(Content-Length 0)], []] + [200, [%w(content-type text/plain), %w(content-length 0)], []] }).call(env({})) }.must_raise(Rack::Lint::LintError). message.must_equal "headers object should be a hash, but isn't (got Array as headers)" @@ -390,18 +399,18 @@ describe Rack::Lint do it "notice content-type errors" do # lambda { # Rack::Lint.new(lambda { |env| - # [200, {"Content-length" => "0"}, []] + # [200, {"content-length" => "0"}, []] # }).call(env({})) # }.must_raise(Rack::Lint::LintError). - # message.must_match(/No Content-Type/) + # message.must_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" }, []] + [status, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). - message.must_match(/Content-Type header found/) + message.must_match(/content-type header found/) end end @@ -409,24 +418,24 @@ describe Rack::Lint do [100, 101, 204, 304].each do |status| lambda { Rack::Lint.new(lambda { |env| - [status, { "Content-length" => "0" }, []] + [status, { "content-length" => "0" }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). - message.must_match(/Content-Length header found/) + message.must_match(/content-length header found/) end lambda { Rack::Lint.new(lambda { |env| - [200, { "Content-type" => "text/plain", "Content-Length" => "1" }, []] + [200, { "content-type" => "text/plain", "content-length" => "1" }, []] }).call(env({}))[2].each { } }.must_raise(Rack::Lint::LintError). - message.must_match(/Content-Length header was 1, but should be 0/) + message.must_match(/content-length header was 1, but should be 0/) end it "notice body errors" do lambda { body = Rack::Lint.new(lambda { |env| - [200, { "Content-type" => "text/plain", "Content-length" => "3" }, [1, 2, 3]] + [200, { "content-type" => "text/plain", "content-length" => "3" }, [1, 2, 3]] }).call(env({}))[2] body.each { |part| } }.must_raise(Rack::Lint::LintError). @@ -442,7 +451,7 @@ describe Rack::Lint do yielder_app = lambda do |_| input = Object.new def input.each; 10.times {yield 'foo'}; end - [200, {"Content-type" => "text/plain", "Content-length" => "30"}, input] + [200, {"content-type" => "text/plain", "content-length" => "30"}, input] end lambda { @@ -495,7 +504,7 @@ describe Rack::Lint do static_app = lambda do |_| input = ['foo'] * 10 - [200, {"Content-type" => "text/plain", "Content-length" => "30"}, input] + [200, {"content-type" => "text/plain", "content-length" => "30"}, input] end lambda { @@ -508,7 +517,7 @@ describe Rack::Lint do input = Object.new def input.to_ary; ['bar'] * 10; end def input.each; 10.times {yield 'foo'}; end - [200, {"Content-type" => "text/plain", "Content-length" => "30"}, input] + [200, {"content-type" => "text/plain", "content-length" => "30"}, input] end lambda { @@ -602,7 +611,7 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env["rack.input"].gets - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env("rack.input" => weirdio)) }.must_raise(Rack::Lint::LintError). message.must_match(/gets didn't return a String/) @@ -610,7 +619,7 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env["rack.input"].each { |x| } - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env("rack.input" => weirdio)) }.must_raise(Rack::Lint::LintError). message.must_match(/each didn't yield a String/) @@ -618,7 +627,7 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env("rack.input" => weirdio)) }.must_raise(Rack::Lint::LintError). message.must_match(/read didn't return nil or a String/) @@ -626,7 +635,7 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env["rack.input"].read - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env("rack.input" => eof_weirdio)) }.must_raise(Rack::Lint::LintError). message.must_match(/read\(nil\) returned nil on EOF/) @@ -634,7 +643,7 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env["rack.input"].close - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). message.must_match(/close must not be called/) @@ -644,7 +653,7 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env["rack.errors"].write(42) - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). message.must_match(/write not called with a String/) @@ -652,7 +661,7 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env["rack.errors"].close - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env({})) }.must_raise(Rack::Lint::LintError). message.must_match(/close must not be called/) @@ -660,12 +669,12 @@ describe Rack::Lint do it "notice HEAD errors" do Rack::Lint.new(lambda { |env| - [200, { "Content-type" => "test/plain", "Content-length" => "3" }, []] + [200, { "content-type" => "test/plain", "content-length" => "3" }, []] }).call(env({ "REQUEST_METHOD" => "HEAD" })).first.must_equal 200 lambda { Rack::Lint.new(lambda { |env| - [200, { "Content-type" => "test/plain", "Content-length" => "3" }, ["foo"]] + [200, { "content-type" => "test/plain", "content-length" => "3" }, ["foo"]] }).call(env({ "REQUEST_METHOD" => "HEAD" }))[2].each { } }.must_raise(Rack::Lint::LintError). message.must_match(/body was given for HEAD/) @@ -677,7 +686,7 @@ describe Rack::Lint do Rack::Lint.new(lambda { |env| env["rack.input"].send(:read, *args) - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env({ "rack.input" => StringIO.new(hello_str) })). first.must_equal 201 end @@ -695,20 +704,20 @@ describe Rack::Lint do lambda { Rack::Lint.new(lambda { |env| env['rack.hijack'].call - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env({ 'rack.hijack?' => true, 'rack.hijack' => lambda { Object.new } })) }.must_raise(Rack::Lint::LintError). message.must_match(/rack.hijack_io must respond to read/) Rack::Lint.new(lambda { |env| env['rack.hijack'].call - [201, { "Content-type" => "text/plain", "Content-length" => "0" }, []] + [201, { "content-type" => "text/plain", "content-length" => "0" }, []] }).call(env({ 'rack.hijack?' => true, 'rack.hijack' => lambda { StringIO.new }, 'rack.hijack_io' => StringIO.new })). first.must_equal 201 Rack::Lint.new(lambda { |env| env['rack.hijack?'] = true - [201, { "Content-type" => "text/plain", "Content-length" => "0", 'rack.hijack' => lambda {|io| io }, 'rack.hijack_io' => StringIO.new }, []] + [201, { "content-type" => "text/plain", "content-length" => "0", 'rack.hijack' => lambda {|io| io }, 'rack.hijack_io' => StringIO.new }, []] }).call(env({}))[1]['rack.hijack'].call(StringIO.new).read.must_equal '' end diff --git a/test/spec_lock.rb b/test/spec_lock.rb index 93695dc1..37c73d28 100644 --- a/test/spec_lock.rb +++ b/test/spec_lock.rb @@ -49,7 +49,7 @@ describe Rack::Lock do def each; %w{ hi mom }.each { |x| yield x }; end }.new - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, response] }) + app = lock_app(lambda { |inner_env| [200, { "content-type" => "text/plain" }, response] }) response = app.call(env)[2] list = [] response.each { |x| list << x } @@ -63,7 +63,7 @@ describe Rack::Lock do res = ['Hello World'] def res.to_path ; "/tmp/hello.txt" ; end - app = Rack::Lock.new(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, res] }, lock) + app = Rack::Lock.new(lambda { |inner_env| [200, { "content-type" => "text/plain" }, res] }, lock) body = app.call(env)[2] body.must_respond_to :to_path @@ -75,7 +75,7 @@ describe Rack::Lock do res = ['Hello World'] - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, res] }) + app = lock_app(lambda { |inner_env| [200, { "content-type" => "text/plain" }, res] }) body = app.call(env)[2] body.wont_respond_to :to_path @@ -90,7 +90,7 @@ describe Rack::Lock do def close; @close_called = true; end }.new - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, response] }) + app = lock_app(lambda { |inner_env| [200, { "content-type" => "text/plain" }, response] }) app.call(env) response.close_called.must_equal false response.close @@ -101,7 +101,7 @@ describe Rack::Lock do lock = Lock.new env = Rack::MockRequest.env_for("/") response = Object.new - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, response] }, lock) + app = lock_app(lambda { |inner_env| [200, { "content-type" => "text/plain" }, response] }, lock) lock.synchronized.must_equal false response = app.call(env)[2] lock.synchronized.must_equal true @@ -111,7 +111,7 @@ describe Rack::Lock do it "return value from app" do env = Rack::MockRequest.env_for("/") - body = [200, { "Content-Type" => "text/plain" }, %w{ hi mom }] + body = [200, { "content-type" => "text/plain" }, %w{ hi mom }] app = lock_app(lambda { |inner_env| body }) res = app.call(env) @@ -123,7 +123,7 @@ describe Rack::Lock do it "call synchronize on lock" do lock = Lock.new env = Rack::MockRequest.env_for("/") - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, %w{ a b c }] }, lock) + app = lock_app(lambda { |inner_env| [200, { "content-type" => "text/plain" }, %w{ a b c }] }, lock) lock.synchronized.must_equal false app.call(env) lock.synchronized.must_equal true @@ -153,7 +153,7 @@ describe Rack::Lock do def unlock() @unlocked = true end end.new env = Rack::MockRequest.env_for("/") - app = lock_app(proc { [200, { "Content-Type" => "text/plain" }, []] }, lock) + app = lock_app(proc { [200, { "content-type" => "text/plain" }, []] }, lock) lambda { app.call(env) }.must_raise Exception lock.unlocked?.must_equal false end @@ -163,7 +163,7 @@ describe Rack::Lock do attr_reader :env def initialize(env) @env = env end end - app = Rack::Lock.new lambda { |env| [200, { "Content-Type" => "text/plain" }, proxy.new(env)] } + app = Rack::Lock.new lambda { |env| [200, { "content-type" => "text/plain" }, proxy.new(env)] } response = app.call(Rack::MockRequest.env_for("/"))[2] end @@ -177,7 +177,7 @@ describe Rack::Lock do it "not replace the environment" do env = Rack::MockRequest.env_for("/") - app = lock_app(lambda { |inner_env| [200, { "Content-Type" => "text/plain" }, [inner_env.object_id.to_s]] }) + app = lock_app(lambda { |inner_env| [200, { "content-type" => "text/plain" }, [inner_env.object_id.to_s]] }) _, _, body = app.call(env) diff --git a/test/spec_logger.rb b/test/spec_logger.rb index 6f63f1ae..26d05def 100644 --- a/test/spec_logger.rb +++ b/test/spec_logger.rb @@ -15,7 +15,7 @@ describe Rack::Logger do log.info("Program started") log.warn("Nothing to do!") - [200, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] + [200, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } it "conform to Rack::Lint" do diff --git a/test/spec_method_override.rb b/test/spec_method_override.rb index 199462db..5205d821 100644 --- a/test/spec_method_override.rb +++ b/test/spec_method_override.rb @@ -11,7 +11,7 @@ end describe Rack::MethodOverride do def app Rack::Lint.new(Rack::MethodOverride.new(lambda {|e| - [200, { "Content-Type" => "text/plain" }, []] + [200, { "content-type" => "text/plain" }, []] })) end @@ -100,7 +100,7 @@ EOF "CONTENT_LENGTH" => input.size.to_s, Rack::RACK_ERRORS => StringIO.new, :method => "POST", :input => input) - Rack::MethodOverride.new(proc { [200, { "Content-Type" => "text/plain" }, []] }).call env + Rack::MethodOverride.new(proc { [200, { "content-type" => "text/plain" }, []] }).call env env[Rack::RACK_ERRORS].rewind env[Rack::RACK_ERRORS].read.must_match /Bad request content body/ diff --git a/test/spec_mock.rb b/test/spec_mock.rb index 072cc352..0c50d6d6 100644 --- a/test/spec_mock.rb +++ b/test/spec_mock.rb @@ -27,7 +27,7 @@ app = Rack::Lint.new(lambda { |env| response = Rack::Response.new( body, req.GET["status"] || 200, - "Content-Type" => "text/yaml" + "content-type" => "text/yaml" ) response.set_cookie("session_test", { value: "session_test", domain: ".test.com", path: "/" }) response.set_cookie("secure_test", { value: "secure_test", domain: ".test.com", path: "/", secure: true }) @@ -233,7 +233,7 @@ describe Rack::MockRequest do it "call close on the original body object" do called = false body = Rack::BodyProxy.new(['hi']) { called = true } - capp = proc { |e| [200, { 'Content-Type' => 'text/plain' }, body] } + capp = proc { |e| [200, { 'content-type' => 'text/plain' }, body] } called.must_equal false Rack::MockRequest.new(capp).get('/', lint: true) called.must_equal true @@ -292,10 +292,10 @@ describe Rack::MockResponse do it "provide access to the HTTP headers" do res = Rack::MockRequest.new(app).get("") - res.must_include "Content-Type" - res.headers["Content-Type"].must_equal "text/yaml" - res.original_headers["Content-Type"].must_equal "text/yaml" - res["Content-Type"].must_equal "text/yaml" + res.must_include "content-type" + res.headers["content-type"].must_equal "text/yaml" + res.original_headers["content-type"].must_equal "text/yaml" + res["content-type"].must_equal "text/yaml" res.content_type.must_equal "text/yaml" res.content_length.wont_equal 0 res.location.must_be_nil @@ -362,13 +362,13 @@ describe Rack::MockResponse do res.cookie("i_dont_exist").must_be_nil end - it "parses cookie headers provided as an array" do + deprecated "parses cookie headers provided as an array" do res = Rack::MockRequest.new(->(env) { [200, [["set-cookie", "array=awesome"]], [""]] }).get("") array_cookie = res.cookie("array") array_cookie.value[0].must_equal "awesome" end - it "parses multiple set-cookie headers provided as an array" do + deprecated "parses multiple set-cookie headers provided as an array" do cookie_headers = [["set-cookie", "array=awesome\nmultiple=times"]] res = Rack::MockRequest.new(->(env) { [200, cookie_headers, [""]] }).get("") array_cookie = res.cookie("array") @@ -402,7 +402,7 @@ describe Rack::MockResponse do res.errors.must_include "foo" end - it "handle enumerable headers that are not a hash" do + deprecated "handle enumerable headers that are not a hash" do # this is exactly what rack-test does res = Rack::MockResponse.new(200, [], []) res.cookies.must_equal({}) @@ -434,21 +434,21 @@ describe Rack::MockResponse, 'headers' do end it 'has_header?' do - lambda { @res.has_header? nil }.must_raise NoMethodError + lambda { @res.has_header? nil }.must_raise ArgumentError @res.has_header?('FOO').must_equal true @res.has_header?('Foo').must_equal true end it 'get_header' do - lambda { @res.get_header nil }.must_raise NoMethodError + lambda { @res.get_header nil }.must_raise ArgumentError @res.get_header('FOO').must_equal '1' @res.get_header('Foo').must_equal '1' end it 'set_header' do - lambda { @res.set_header nil, '1' }.must_raise NoMethodError + lambda { @res.set_header nil, '1' }.must_raise ArgumentError @res.set_header('FOO', '2').must_equal '2' @res.get_header('FOO').must_equal '2' @@ -463,7 +463,7 @@ describe Rack::MockResponse, 'headers' do end it 'add_header' do - lambda { @res.add_header nil, '1' }.must_raise NoMethodError + lambda { @res.add_header nil, '1' }.must_raise ArgumentError # Sets header on first addition @res.add_header('FOO', '1').must_equal '1,1' @@ -484,7 +484,7 @@ describe Rack::MockResponse, 'headers' do end it 'delete_header' do - lambda { @res.delete_header nil }.must_raise NoMethodError + lambda { @res.delete_header nil }.must_raise ArgumentError @res.delete_header('FOO').must_equal '1' @res.has_header?('FOO').must_equal false diff --git a/test/spec_null_logger.rb b/test/spec_null_logger.rb index 8659a8e5..698b07eb 100644 --- a/test/spec_null_logger.rb +++ b/test/spec_null_logger.rb @@ -12,14 +12,14 @@ describe Rack::NullLogger do it "act as a noop logger" do app = lambda { |env| env['rack.logger'].warn "b00m" - [200, { 'Content-Type' => 'text/plain' }, ["Hello, World!"]] + [200, { 'content-type' => 'text/plain' }, ["Hello, World!"]] } logger = Rack::Lint.new(Rack::NullLogger.new(app)) res = logger.call(Rack::MockRequest.env_for) res[0..1].must_equal [ - 200, { 'Content-Type' => 'text/plain' } + 200, { 'content-type' => 'text/plain' } ] res[2].to_enum.to_a.must_equal ["Hello, World!"] end diff --git a/test/spec_recursive.rb b/test/spec_recursive.rb index 1691066e..23e6487b 100644 --- a/test/spec_recursive.rb +++ b/test/spec_recursive.rb @@ -13,8 +13,8 @@ describe Rack::Recursive do before do @app1 = lambda { |env| res = Rack::Response.new - res["X-Path-Info"] = env["PATH_INFO"] - res["X-Query-String"] = env["QUERY_STRING"] + res["x-path-info"] = env["PATH_INFO"] + res["x-query-string"] = env["QUERY_STRING"] res.finish do |inner_res| inner_res.write "App1" end @@ -75,7 +75,7 @@ describe Rack::Recursive do res = Rack::MockRequest.new(app).get("/app4") res.must_be :ok? res.body.must_equal "App1" - res["X-Path-Info"].must_equal "/quux" - res["X-Query-String"].must_equal "meh" + res["x-path-info"].must_equal "/quux" + res["x-query-string"].must_equal "meh" end end diff --git a/test/spec_request.rb b/test/spec_request.rb index a354df0a..92316f38 100644 --- a/test/spec_request.rb +++ b/test/spec_request.rb @@ -1212,7 +1212,7 @@ EOF app = lambda { |env| content = make_request(env).POST["file"].inspect size = content.bytesize - [200, { "Content-Type" => "text/html", "Content-Length" => size.to_s }, [content]] + [200, { "content-type" => "text/html", "content-length" => size.to_s }, [content]] } input = <<EOF.dup diff --git a/test/spec_response.rb b/test/spec_response.rb index 3c25aa0c..91cdfbb4 100644 --- a/test/spec_response.rb +++ b/test/spec_response.rb @@ -23,7 +23,7 @@ describe Rack::Response do cc = 'foo' response.cache_control = cc assert_equal cc, response.cache_control - assert_equal cc, response.to_a[1]['Cache-Control'] + assert_equal cc, response.to_a[1]['cache-control'] end it 'has an etag method' do @@ -628,9 +628,9 @@ describe Rack::Response do response.cache!(1000) response.do_not_cache! - expect(response['Cache-Control']).must_equal "no-cache, must-revalidate" + expect(response['cache-control']).must_equal "no-cache, must-revalidate" - expires_header = Time.parse(response['Expires']) + expires_header = Time.parse(response['expires']) expect(expires_header).must_be :<=, Time.now end @@ -641,34 +641,34 @@ describe Rack::Response do expires = Time.now + 100 # At least this far into the future response.cache!(duration) - expect(response['Cache-Control']).must_equal "public, max-age=120" + expect(response['cache-control']).must_equal "public, max-age=120" - expires_header = Time.parse(response['Expires']) + expires_header = Time.parse(response['expires']) expect(expires_header).must_be :>=, expires end end describe Rack::Response, 'headers' do before do - @response = Rack::Response.new([], 200, { 'Foo' => '1' }) + @response = Rack::Response.new([], 200, { 'foo' => '1' }) end it 'has_header?' do - lambda { @response.has_header? nil }.must_raise NoMethodError + lambda { @response.has_header? nil }.must_raise ArgumentError @response.has_header?('Foo').must_equal true @response.has_header?('foo').must_equal true end it 'get_header' do - lambda { @response.get_header nil }.must_raise NoMethodError + lambda { @response.get_header nil }.must_raise ArgumentError @response.get_header('Foo').must_equal '1' @response.get_header('foo').must_equal '1' end it 'set_header' do - lambda { @response.set_header nil, '1' }.must_raise NoMethodError + lambda { @response.set_header nil, '1' }.must_raise ArgumentError @response.set_header('Foo', '2').must_equal '2' @response.has_header?('Foo').must_equal true @@ -680,7 +680,7 @@ describe Rack::Response, 'headers' do end it 'add_header' do - lambda { @response.add_header nil, '1' }.must_raise NoMethodError + lambda { @response.add_header nil, '1' }.must_raise ArgumentError # Add a value to an existing header @response.add_header('Foo', '2').must_equal '1,2' @@ -702,7 +702,7 @@ describe Rack::Response, 'headers' do end it 'delete_header' do - lambda { @response.delete_header nil }.must_raise NoMethodError + lambda { @response.delete_header nil }.must_raise ArgumentError @response.delete_header('Foo').must_equal '1' (!!@response.has_header?('Foo')).must_equal false diff --git a/test/spec_runtime.rb b/test/spec_runtime.rb index 0b927e9a..0e22d2b5 100644 --- a/test/spec_runtime.rb +++ b/test/spec_runtime.rb @@ -17,32 +17,26 @@ describe Rack::Runtime do Rack::MockRequest.env_for end - it "works even if headers is an array" do - app = lambda { |env| [200, [['Content-Type', 'text/plain']], "Hello, World!"] } + it "sets x-runtime is none is set" do + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, "Hello, World!"] } response = runtime_app(app).call(request) - response[1]['X-Runtime'].must_match(/[\d\.]+/) + response[1]['x-runtime'].must_match(/[\d\.]+/) end - it "sets X-Runtime is none is set" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, "Hello, World!"] } + it "doesn't set the x-runtime if it is already set" do + app = lambda { |env| [200, { 'content-type' => 'text/plain', "x-runtime" => "foobar" }, "Hello, World!"] } response = runtime_app(app).call(request) - response[1]['X-Runtime'].must_match(/[\d\.]+/) - end - - it "doesn't set the X-Runtime if it is already set" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain', "X-Runtime" => "foobar" }, "Hello, World!"] } - response = runtime_app(app).call(request) - response[1]['X-Runtime'].must_equal "foobar" + response[1]['x-runtime'].must_equal "foobar" end it "allow a suffix to be set" do - app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, "Hello, World!"] } + app = lambda { |env| [200, { 'content-type' => 'text/plain' }, "Hello, World!"] } response = runtime_app(app, "Test").call(request) - response[1]['X-Runtime-Test'].must_match(/[\d\.]+/) + response[1]['x-runtime-test'].must_match(/[\d\.]+/) end it "allow multiple timers to be set" do - app = lambda { |env| sleep 0.1; [200, { 'Content-Type' => 'text/plain' }, "Hello, World!"] } + app = lambda { |env| sleep 0.1; [200, { 'content-type' => 'text/plain' }, "Hello, World!"] } runtime = runtime_app(app, "App") # wrap many times to guarantee a measurable difference @@ -53,9 +47,9 @@ describe Rack::Runtime do response = runtime.call(request) - response[1]['X-Runtime-App'].must_match(/[\d\.]+/) - response[1]['X-Runtime-All'].must_match(/[\d\.]+/) + response[1]['x-runtime-app'].must_match(/[\d\.]+/) + response[1]['x-runtime-all'].must_match(/[\d\.]+/) - Float(response[1]['X-Runtime-All']).must_be :>, Float(response[1]['X-Runtime-App']) + Float(response[1]['x-runtime-all']).must_be :>, Float(response[1]['x-runtime-app']) end end diff --git a/test/spec_sendfile.rb b/test/spec_sendfile.rb index f69a3e41..ff7045b6 100644 --- a/test/spec_sendfile.rb +++ b/test/spec_sendfile.rb @@ -19,7 +19,7 @@ describe Rack::Sendfile do end def simple_app(body = sendfile_body) - lambda { |env| [200, { 'Content-Type' => 'text/plain' }, body] } + lambda { |env| [200, { 'content-type' => 'text/plain' }, body] } end def sendfile_app(body, mappings = []) @@ -38,32 +38,32 @@ describe Rack::Sendfile do end.open(path, 'wb+') end - it "does nothing when no X-Sendfile-Type header present" do + it "does nothing when no x-sendfile-Type header present" do request do |response| response.must_be :ok? response.body.must_equal 'Hello World' - response.headers.wont_include 'X-Sendfile' + response.headers.wont_include 'x-sendfile' end end - it "does nothing and logs to rack.errors when incorrect X-Sendfile-Type header present" do + it "does nothing and logs to rack.errors when incorrect x-sendfile-Type header present" do io = StringIO.new request 'HTTP_X_SENDFILE_TYPE' => 'X-Banana', 'rack.errors' => io do |response| response.must_be :ok? response.body.must_equal 'Hello World' - response.headers.wont_include 'X-Sendfile' + response.headers.wont_include 'x-sendfile' io.rewind io.read.must_equal "Unknown x-sendfile variation: 'X-Banana'.\n" end end - it "sets X-Sendfile response header and discards body" do - request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response| + it "sets x-sendfile response header and discards body" do + request 'HTTP_X_SENDFILE_TYPE' => 'x-sendfile' do |response| response.must_be :ok? response.body.must_be :empty? response.headers['Content-Length'].must_equal '0' - response.headers['X-Sendfile'].must_equal File.join(Dir.tmpdir, "rack_sendfile") + response.headers['x-sendfile'].must_equal File.join(Dir.tmpdir, "rack_sendfile") end end @@ -112,9 +112,9 @@ describe Rack::Sendfile do end it 'does nothing when body does not respond to #to_path' do - request({ 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' }, ['Not a file...']) do |response| + request({ 'HTTP_X_SENDFILE_TYPE' => 'x-sendfile' }, ['Not a file...']) do |response| response.body.must_equal 'Not a file...' - response.headers.wont_include 'X-Sendfile' + response.headers.wont_include 'x-sendfile' end end diff --git a/test/spec_server.rb b/test/spec_server.rb index 1e2d7cfa..070d6c4e 100644 --- a/test/spec_server.rb +++ b/test/spec_server.rb @@ -166,7 +166,7 @@ describe Rack::Server do def (server.server).run(app, **) app end s, h, b = server.start.call('rack.errors' => StringIO.new) s.must_equal 500 - h['Content-Type'].must_equal 'text/plain' + h['content-type'].must_equal 'text/plain' b.join.must_include 'Rack::Lint::LintError' end diff --git a/test/spec_show_status.rb b/test/spec_show_status.rb index e8d88b41..c5608c04 100644 --- a/test/spec_show_status.rb +++ b/test/spec_show_status.rb @@ -16,14 +16,14 @@ describe Rack::ShowStatus do it "provide a default status message" do req = Rack::MockRequest.new( show_status(lambda{|env| - [404, { "Content-Type" => "text/plain", "Content-Length" => "0" }, []] + [404, { "content-type" => "text/plain", "content-length" => "0" }, []] })) res = req.get("/", lint: true) res.must_be :not_found? res.wont_be_empty - res["Content-Type"].must_equal "text/html" + res["content-type"].must_equal "text/html" assert_match(res, /404/) assert_match(res, /Not Found/) end @@ -33,14 +33,14 @@ describe Rack::ShowStatus do show_status( lambda{|env| env["rack.showstatus.detail"] = "gone too meta." - [404, { "Content-Type" => "text/plain", "Content-Length" => "0" }, []] + [404, { "content-type" => "text/plain", "content-length" => "0" }, []] })) res = req.get("/", lint: true) res.must_be :not_found? res.wont_be_empty - res["Content-Type"].must_equal "text/html" + res["content-type"].must_equal "text/html" assert_match(res, /404/) assert_match(res, /Not Found/) assert_match(res, /too meta/) @@ -51,14 +51,14 @@ describe Rack::ShowStatus do show_status( lambda{|env| env["rack.showstatus.detail"] = ['gone too meta.'] - [404, { "Content-Type" => "text/plain", "Content-Length" => "0" }, []] + [404, { "content-type" => "text/plain", "content-length" => "0" }, []] })) res = req.get("/", lint: true) res.must_be :not_found? res.wont_be_empty - res["Content-Type"].must_equal "text/html" + res["content-type"].must_equal "text/html" assert_includes(res.body, '404') assert_includes(res.body, 'Not Found') assert_includes(res.body, '["gone too meta."]') @@ -70,13 +70,13 @@ describe Rack::ShowStatus do show_status( lambda{|env| env["rack.showstatus.detail"] = detail - [500, { "Content-Type" => "text/plain", "Content-Length" => "0" }, []] + [500, { "content-type" => "text/plain", "content-length" => "0" }, []] })) res = req.get("/", lint: true) res.wont_be_empty - res["Content-Type"].must_equal "text/html" + res["content-type"].must_equal "text/html" assert_match(res, /500/) res.wont_include detail res.body.must_include Rack::Utils.escape_html(detail) @@ -86,7 +86,7 @@ describe Rack::ShowStatus do req = Rack::MockRequest.new( show_status( lambda{|env| - [404, { "Content-Type" => "text/plain", "Content-Length" => "4" }, ["foo!"]] + [404, { "content-type" => "text/plain", "content-length" => "4" }, ["foo!"]] })) res = req.get("/", lint: true) @@ -96,13 +96,13 @@ describe Rack::ShowStatus do end it "pass on original headers" do - headers = { "WWW-Authenticate" => "Basic blah" } + headers = { "www-authenticate" => "Basic blah" } req = Rack::MockRequest.new( show_status(lambda{|env| [401, headers, []] })) res = req.get("/", lint: true) - res["WWW-Authenticate"].must_equal "Basic blah" + res["www-authenticate"].must_equal "Basic blah" end it "replace existing messages if there is detail" do @@ -110,15 +110,15 @@ describe Rack::ShowStatus do show_status( lambda{|env| env["rack.showstatus.detail"] = "gone too meta." - [404, { "Content-Type" => "text/plain", "Content-Length" => "4" }, ["foo!"]] + [404, { "content-type" => "text/plain", "content-length" => "4" }, ["foo!"]] })) res = req.get("/", lint: true) res.must_be :not_found? res.wont_be_empty - res["Content-Type"].must_equal "text/html" - res["Content-Length"].wont_equal "4" + res["content-type"].must_equal "text/html" + res["content-length"].wont_equal "4" assert_match(res, /404/) assert_match(res, /too meta/) res.body.wont_match(/foo/) @@ -133,7 +133,7 @@ describe Rack::ShowStatus do req = Rack::MockRequest.new( show_status(lambda{|env| - [404, { "Content-Type" => "text/plain", "Content-Length" => "0" }, body] + [404, { "content-type" => "text/plain", "content-length" => "0" }, body] })) response = req.get("/", lint: true) diff --git a/test/spec_static.rb b/test/spec_static.rb index b8c02b1f..fc242ded 100644 --- a/test/spec_static.rb +++ b/test/spec_static.rb @@ -11,7 +11,7 @@ end class DummyApp def call(env) - [200, { "Content-Type" => "text/plain" }, ["Hello World"]] + [200, { "content-type" => "text/plain" }, ["Hello World"]] end end @@ -122,7 +122,7 @@ describe Rack::Static do res = @gzip_request.get("/cgi/test", 'HTTP_ACCEPT_ENCODING' => 'deflate, gzip') res.must_be :ok? res.headers['Content-Encoding'].must_equal 'gzip' - res.headers['Content-Type'].must_equal 'text/plain' + res.headers['content-type'].must_equal 'text/plain' Zlib::GzipReader.wrap(StringIO.new(res.body), &:read).must_match(/ruby/) end @@ -130,7 +130,7 @@ describe Rack::Static do res = @gzip_request.get("/cgi/rackup_stub.rb", 'HTTP_ACCEPT_ENCODING' => 'deflate, gzip') res.must_be :ok? res.headers['Content-Encoding'].must_be_nil - res.headers['Content-Type'].must_equal 'text/x-script.ruby' + res.headers['content-type'].must_equal 'text/x-script.ruby' res.body.must_match(/ruby/) end @@ -138,7 +138,7 @@ describe Rack::Static do res = @gzip_request.get("/cgi/test") res.must_be :ok? res.headers['Content-Encoding'].must_be_nil - res.headers['Content-Type'].must_equal 'text/plain' + res.headers['content-type'].must_equal 'text/plain' res.body.must_match(/ruby/) end @@ -148,7 +148,7 @@ describe Rack::Static do res.status.must_equal 304 res.body.must_be :empty? res.headers['Content-Encoding'].must_be_nil - res.headers['Content-Type'].must_be_nil + res.headers['content-type'].must_be_nil end it "supports serving fixed cache-control (legacy option)" do @@ -156,71 +156,71 @@ describe Rack::Static do request = Rack::MockRequest.new(static(DummyApp.new, opts)) res = request.get("/cgi/test") res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public' + res.headers['cache-control'].must_equal 'public' end HEADER_OPTIONS = { urls: ["/cgi"], root: root, header_rules: [ - [:all, { 'Cache-Control' => 'public, max-age=100' }], - [:fonts, { 'Cache-Control' => 'public, max-age=200' }], - [%w(png jpg), { 'Cache-Control' => 'public, max-age=300' }], - ['/cgi/assets/folder/', { 'Cache-Control' => 'public, max-age=400' }], - ['cgi/assets/javascripts', { 'Cache-Control' => 'public, max-age=500' }], - [/\.(css|erb)\z/, { 'Cache-Control' => 'public, max-age=600' }], - [false, { 'Cache-Control' => 'public, max-age=600' }] + [:all, { 'cache-control' => 'public, max-age=100' }], + [:fonts, { 'cache-control' => 'public, max-age=200' }], + [%w(png jpg), { 'cache-control' => 'public, max-age=300' }], + ['/cgi/assets/folder/', { 'cache-control' => 'public, max-age=400' }], + ['cgi/assets/javascripts', { 'cache-control' => 'public, max-age=500' }], + [/\.(css|erb)\z/, { 'cache-control' => 'public, max-age=600' }], + [false, { 'cache-control' => 'public, max-age=600' }] ] } it "supports header rule :all" do # Headers for all files via :all shortcut res = @header_request.get('/cgi/assets/index.html') res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public, max-age=100' + res.headers['cache-control'].must_equal 'public, max-age=100' end it "supports header rule :fonts" do # Headers for web fonts via :fonts shortcut res = @header_request.get('/cgi/assets/fonts/font.eot') res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public, max-age=200' + res.headers['cache-control'].must_equal 'public, max-age=200' end it "supports file extension header rules provided as an Array" do # Headers for file extensions via array res = @header_request.get('/cgi/assets/images/image.png') res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public, max-age=300' + res.headers['cache-control'].must_equal 'public, max-age=300' end it "supports folder rules provided as a String" do # Headers for files in folder via string res = @header_request.get('/cgi/assets/folder/test.js') res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public, max-age=400' + res.headers['cache-control'].must_equal 'public, max-age=400' end it "supports folder header rules provided as a String not starting with a slash" do res = @header_request.get('/cgi/assets/javascripts/app.js') res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public, max-age=500' + res.headers['cache-control'].must_equal 'public, max-age=500' end it "supports flexible header rules provided as Regexp" do # Flexible Headers via Regexp res = @header_request.get('/cgi/assets/stylesheets/app.css') res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public, max-age=600' + res.headers['cache-control'].must_equal 'public, max-age=600' end it "prioritizes header rules over fixed cache-control setting (legacy option)" do opts = OPTIONS.merge( cache_control: 'public, max-age=24', header_rules: [ - [:all, { 'Cache-Control' => 'public, max-age=42' }] + [:all, { 'cache-control' => 'public, max-age=42' }] ]) request = Rack::MockRequest.new(static(DummyApp.new, opts)) res = request.get("/cgi/test") res.must_be :ok? - res.headers['Cache-Control'].must_equal 'public, max-age=42' + res.headers['cache-control'].must_equal 'public, max-age=42' end it "expands the root path upon the middleware initialization" do diff --git a/test/spec_urlmap.rb b/test/spec_urlmap.rb index db3c676a..855e4541 100644 --- a/test/spec_urlmap.rb +++ b/test/spec_urlmap.rb @@ -12,9 +12,9 @@ describe Rack::URLMap do it "dispatches paths correctly" do app = lambda { |env| [200, { - 'X-ScriptName' => env['SCRIPT_NAME'], - 'X-PathInfo' => env['PATH_INFO'], - 'Content-Type' => 'text/plain' + 'x-scriptname' => env['SCRIPT_NAME'], + 'x-pathinfo' => env['PATH_INFO'], + 'content-type' => 'text/plain' }, [""]] } map = Rack::Lint.new(Rack::URLMap.new({ @@ -31,111 +31,111 @@ describe Rack::URLMap do res = Rack::MockRequest.new(map).get("/foo") res.must_be :ok? - res["X-ScriptName"].must_equal "/foo" - res["X-PathInfo"].must_equal "" + res["x-scriptname"].must_equal "/foo" + res["x-pathinfo"].must_equal "" res = Rack::MockRequest.new(map).get("/foo/") res.must_be :ok? - res["X-ScriptName"].must_equal "/foo" - res["X-PathInfo"].must_equal "/" + res["x-scriptname"].must_equal "/foo" + res["x-pathinfo"].must_equal "/" res = Rack::MockRequest.new(map).get("/foo/bar") res.must_be :ok? - res["X-ScriptName"].must_equal "/foo/bar" - res["X-PathInfo"].must_equal "" + res["x-scriptname"].must_equal "/foo/bar" + res["x-pathinfo"].must_equal "" res = Rack::MockRequest.new(map).get("/foo/bar/") res.must_be :ok? - res["X-ScriptName"].must_equal "/foo/bar" - res["X-PathInfo"].must_equal "/" + res["x-scriptname"].must_equal "/foo/bar" + res["x-pathinfo"].must_equal "/" res = Rack::MockRequest.new(map).get("/foo///bar//quux") res.status.must_equal 200 res.must_be :ok? - res["X-ScriptName"].must_equal "/foo/bar" - res["X-PathInfo"].must_equal "//quux" + res["x-scriptname"].must_equal "/foo/bar" + res["x-pathinfo"].must_equal "//quux" res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh") res.must_be :ok? - res["X-ScriptName"].must_equal "/bleh/foo" - res["X-PathInfo"].must_equal "/quux" + res["x-scriptname"].must_equal "/bleh/foo" + res["x-pathinfo"].must_equal "/quux" res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org') res.must_be :ok? - res["X-ScriptName"].must_equal "/bar" - res["X-PathInfo"].must_be :empty? + res["x-scriptname"].must_equal "/bar" + res["x-pathinfo"].must_be :empty? res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org') res.must_be :ok? - res["X-ScriptName"].must_equal "/bar" - res["X-PathInfo"].must_equal '/' + res["x-scriptname"].must_equal "/bar" + res["x-pathinfo"].must_equal '/' end it "dispatches hosts correctly" do map = Rack::Lint.new(Rack::URLMap.new("http://foo.org/" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "foo.org", - "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + { "content-type" => "text/plain", + "x-position" => "foo.org", + "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]}, "http://subdomain.foo.org/" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "subdomain.foo.org", - "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + { "content-type" => "text/plain", + "x-position" => "subdomain.foo.org", + "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]}, "http://bar.org/" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "bar.org", - "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + { "content-type" => "text/plain", + "x-position" => "bar.org", + "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]}, "/" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "default.org", - "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"], + { "content-type" => "text/plain", + "x-position" => "default.org", + "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"], }, [""]]} )) res = Rack::MockRequest.new(map).get("/") res.must_be :ok? - res["X-Position"].must_equal "default.org" + res["x-position"].must_equal "default.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org") res.must_be :ok? - res["X-Position"].must_equal "bar.org" + res["x-position"].must_equal "bar.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org") res.must_be :ok? - res["X-Position"].must_equal "foo.org" + res["x-position"].must_equal "foo.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org") res.must_be :ok? - res["X-Position"].must_equal "subdomain.foo.org" + res["x-position"].must_equal "subdomain.foo.org" res = Rack::MockRequest.new(map).get("http://foo.org/") res.must_be :ok? - res["X-Position"].must_equal "foo.org" + res["x-position"].must_equal "foo.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org") res.must_be :ok? - res["X-Position"].must_equal "default.org" + res["x-position"].must_equal "default.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "any-host.org") res.must_be :ok? - res["X-Position"].must_equal "default.org" + res["x-position"].must_equal "default.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "any-host.org", "HTTP_X_FORWARDED_HOST" => "any-host.org") res.must_be :ok? - res["X-Position"].must_equal "default.org" + res["x-position"].must_equal "default.org" res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org:9292", "SERVER_PORT" => "9292") res.must_be :ok? - res["X-Position"].must_equal "default.org" + res["x-position"].must_equal "default.org" end it "be nestable" do @@ -143,10 +143,10 @@ describe Rack::URLMap do Rack::URLMap.new("/bar" => Rack::URLMap.new("/quux" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "/foo/bar/quux", - "X-PathInfo" => env["PATH_INFO"], - "X-ScriptName" => env["SCRIPT_NAME"], + { "content-type" => "text/plain", + "x-position" => "/foo/bar/quux", + "x-pathinfo" => env["PATH_INFO"], + "x-scriptname" => env["SCRIPT_NAME"], }, [""]]} )))) @@ -155,98 +155,98 @@ describe Rack::URLMap do res = Rack::MockRequest.new(map).get("/foo/bar/quux") res.must_be :ok? - res["X-Position"].must_equal "/foo/bar/quux" - res["X-PathInfo"].must_equal "" - res["X-ScriptName"].must_equal "/foo/bar/quux" + res["x-position"].must_equal "/foo/bar/quux" + res["x-pathinfo"].must_equal "" + res["x-scriptname"].must_equal "/foo/bar/quux" end it "route root apps correctly" do map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "root", - "X-PathInfo" => env["PATH_INFO"], - "X-ScriptName" => env["SCRIPT_NAME"] + { "content-type" => "text/plain", + "x-position" => "root", + "x-pathinfo" => env["PATH_INFO"], + "x-scriptname" => env["SCRIPT_NAME"] }, [""]]}, "/foo" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "foo", - "X-PathInfo" => env["PATH_INFO"], - "X-ScriptName" => env["SCRIPT_NAME"] + { "content-type" => "text/plain", + "x-position" => "foo", + "x-pathinfo" => env["PATH_INFO"], + "x-scriptname" => env["SCRIPT_NAME"] }, [""]]} )) res = Rack::MockRequest.new(map).get("/foo/bar") res.must_be :ok? - res["X-Position"].must_equal "foo" - res["X-PathInfo"].must_equal "/bar" - res["X-ScriptName"].must_equal "/foo" + res["x-position"].must_equal "foo" + res["x-pathinfo"].must_equal "/bar" + res["x-scriptname"].must_equal "/foo" res = Rack::MockRequest.new(map).get("/foo") res.must_be :ok? - res["X-Position"].must_equal "foo" - res["X-PathInfo"].must_equal "" - res["X-ScriptName"].must_equal "/foo" + res["x-position"].must_equal "foo" + res["x-pathinfo"].must_equal "" + res["x-scriptname"].must_equal "/foo" res = Rack::MockRequest.new(map).get("/bar") res.must_be :ok? - res["X-Position"].must_equal "root" - res["X-PathInfo"].must_equal "/bar" - res["X-ScriptName"].must_equal "" + res["x-position"].must_equal "root" + res["x-pathinfo"].must_equal "/bar" + res["x-scriptname"].must_equal "" res = Rack::MockRequest.new(map).get("") res.must_be :ok? - res["X-Position"].must_equal "root" - res["X-PathInfo"].must_equal "/" - res["X-ScriptName"].must_equal "" + res["x-position"].must_equal "root" + res["x-pathinfo"].must_equal "/" + res["x-scriptname"].must_equal "" end it "not squeeze slashes" do map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "root", - "X-PathInfo" => env["PATH_INFO"], - "X-ScriptName" => env["SCRIPT_NAME"] + { "content-type" => "text/plain", + "x-position" => "root", + "x-pathinfo" => env["PATH_INFO"], + "x-scriptname" => env["SCRIPT_NAME"] }, [""]]}, "/foo" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "foo", - "X-PathInfo" => env["PATH_INFO"], - "X-ScriptName" => env["SCRIPT_NAME"] + { "content-type" => "text/plain", + "x-position" => "foo", + "x-pathinfo" => env["PATH_INFO"], + "x-scriptname" => env["SCRIPT_NAME"] }, [""]]} )) res = Rack::MockRequest.new(map).get("/http://example.org/bar") res.must_be :ok? - res["X-Position"].must_equal "root" - res["X-PathInfo"].must_equal "/http://example.org/bar" - res["X-ScriptName"].must_equal "" + res["x-position"].must_equal "root" + res["x-pathinfo"].must_equal "/http://example.org/bar" + res["x-scriptname"].must_equal "" end it "not be case sensitive with hosts" do map = Rack::Lint.new(Rack::URLMap.new("http://example.org/" => lambda { |env| [200, - { "Content-Type" => "text/plain", - "X-Position" => "root", - "X-PathInfo" => env["PATH_INFO"], - "X-ScriptName" => env["SCRIPT_NAME"] + { "content-type" => "text/plain", + "x-position" => "root", + "x-pathinfo" => env["PATH_INFO"], + "x-scriptname" => env["SCRIPT_NAME"] }, [""]]} )) res = Rack::MockRequest.new(map).get("http://example.org/") res.must_be :ok? - res["X-Position"].must_equal "root" - res["X-PathInfo"].must_equal "/" - res["X-ScriptName"].must_equal "" + res["x-position"].must_equal "root" + res["x-pathinfo"].must_equal "/" + res["x-scriptname"].must_equal "" res = Rack::MockRequest.new(map).get("http://EXAMPLE.ORG/") res.must_be :ok? - res["X-Position"].must_equal "root" - res["X-PathInfo"].must_equal "/" - res["X-ScriptName"].must_equal "" + res["x-position"].must_equal "root" + res["x-pathinfo"].must_equal "/" + res["x-scriptname"].must_equal "" end it "not allow locations unless they start with /" do diff --git a/test/spec_utils.rb b/test/spec_utils.rb index e588970b..2e2bbb51 100644 --- a/test/spec_utils.rb +++ b/test/spec_utils.rb @@ -131,30 +131,12 @@ describe Rack::Utils do Rack::Utils.parse_nested_query(nil).must_equal({}) end - it "should warn using deprecated Rack::Util.key_space_limit=" do - begin - warn_arg = nil - Rack::Utils.define_singleton_method(:warn) do |*args| - warn_arg = args.first - end - Rack::Utils.key_space_limit = 65536 - warn_arg.must_equal("`Rack::Utils.key_space_limit=` is deprecated and no longer has an effect. It will be removed in a future version of Rack") - ensure - Rack::Utils.singleton_class.send(:remove_method, :warn) - end + deprecated "should warn using deprecated Rack::Util.key_space_limit=" do + Rack::Utils.key_space_limit = 65536 end - it "should warn using deprecated Rack::Util.key_space_limit" do - begin - warn_arg = nil - Rack::Utils.define_singleton_method(:warn) do |*args| - warn_arg = args.first - end - Rack::Utils.key_space_limit - warn_arg.must_equal("`Rack::Utils.key_space_limit` is deprecated as this value no longer has an effect. It will be removed in a future version of Rack") - ensure - Rack::Utils.singleton_class.send(:remove_method, :warn) - end + deprecated "should warn using deprecated Rack::Util.key_space_limit" do + Rack::Utils.key_space_limit end it "raise an exception if the params are too deep" do @@ -604,26 +586,26 @@ describe Rack::Utils, "cookies" do end it "sets and deletes cookies in header hash" do - header = { 'Set-Cookie' => '' } + header = { 'set-cookie' => '' } Rack::Utils.set_cookie_header!(header, 'name', 'value').must_be_nil - header['Set-Cookie'].must_equal 'name=value' + header['set-cookie'].must_equal 'name=value' Rack::Utils.set_cookie_header!(header, 'name2', 'value2').must_be_nil - header['Set-Cookie'].must_equal "name=value\nname2=value2" + header['set-cookie'].must_equal "name=value\nname2=value2" Rack::Utils.set_cookie_header!(header, 'name2', 'value3').must_be_nil - header['Set-Cookie'].must_equal "name=value\nname2=value2\nname2=value3" + header['set-cookie'].must_equal "name=value\nname2=value2\nname2=value3" Rack::Utils.delete_cookie_header!(header, 'name2').must_be_nil - header['Set-Cookie'].must_equal "name=value\nname2=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" + header['set-cookie'].must_equal "name=value\nname2=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" Rack::Utils.delete_cookie_header!(header, 'name').must_be_nil - header['Set-Cookie'].must_equal "name2=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT\nname=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" + header['set-cookie'].must_equal "name2=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT\nname=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" - header = { 'Set-Cookie' => nil } + header = { 'set-cookie' => nil } Rack::Utils.delete_cookie_header!(header, 'name').must_be_nil - header['Set-Cookie'].must_equal "name=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" + header['set-cookie'].must_equal "name=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" - header = { 'Set-Cookie' => [] } + header = { 'set-cookie' => [] } Rack::Utils.delete_cookie_header!(header, 'name').must_be_nil - header['Set-Cookie'].must_equal "name=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" + header['set-cookie'].must_equal "name=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT" end end @@ -676,167 +658,24 @@ describe Rack::Utils, "byte_range" do end describe Rack::Utils::HeaderHash do - it "retain header case" do - h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") - h['ETag'] = 'Boo!' - h.to_hash.must_equal "Content-MD5" => "d5ff4e2a0 ...", "ETag" => 'Boo!' - end - - it "check existence of keys case insensitively" do - h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") - h.must_include 'content-md5' - h.wont_include 'ETag' - end - - it "fetches values via case-insensitive keys" do - h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") - v = h.fetch("content-MD5", "nope") - v.must_equal "d5ff4e2a0 ..." - end - - it "fetches values via case-insensitive keys without defaults" do - h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") - v = h.fetch("content-MD5") - v.must_equal "d5ff4e2a0 ..." - end + deprecated ".[] returns instance of Rack::Headers" do + h = Rack::Utils::HeaderHash["Content-MD5" => "d5ff4e2a0 ..."] + h.must_be_kind_of Rack::Headers + h['content-md5'].must_equal "d5ff4e2a0 ..." - it "correctly raises an exception on fetch for a non-existent key" do - h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") - - -> { h.fetch("Set-Cookie") }.must_raise(KeyError) + h = Rack::Utils::HeaderHash[[["Content-MD5","d5ff4e2a0 ..."]]] + h.must_be_kind_of Rack::Headers + h['content-md5'].must_equal "d5ff4e2a0 ..." end - it "returns default on fetch miss" do + deprecated ".new returns instance of Rack::Headers" do h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") + h.must_be_kind_of Rack::Headers + h['content-md5'].must_equal "d5ff4e2a0 ..." - v = h.fetch("Missing-Header", "default") - v.must_equal "default" - end - - it "returns default on fetch miss using block" do - h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") - - v = h.fetch("Missing-Header") { |el| "Didn't find #{el}" } - v.must_equal "Didn't find Missing-Header" - end - - it "create deep HeaderHash copy on dup" do - h1 = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...") - h2 = h1.dup - - h1.must_include 'content-md5' - h2.must_include 'content-md5' - - h2.delete("Content-MD5") - - h2.wont_include 'content-md5' - h1.must_include 'content-md5' - end - - it "merge case-insensitively" do - h = Rack::Utils::HeaderHash.new("ETag" => 'HELLO', "content-length" => '123') - merged = h.merge("Etag" => 'WORLD', 'Content-Length' => '321', "Foo" => 'BAR') - merged.must_equal "Etag" => 'WORLD', "Content-Length" => '321', "Foo" => 'BAR' - end - - it "overwrite case insensitively and assume the new key's case" do - h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz") - h["foo-bar"] = "bizzle" - h["FOO-BAR"].must_equal "bizzle" - h.length.must_equal 1 - h.to_hash.must_equal "foo-bar" => "bizzle" - end - - it "be converted to real Hash" do - h = Rack::Utils::HeaderHash.new("foo" => "bar") - h.to_hash.must_be_instance_of Hash - end - - it "convert Array values to Strings when converting to Hash" do - h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"]) - h.to_hash.must_equal({ "foo" => "bar\nbaz" }) - end - - it "replace hashes correctly" do - h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz") - j = { "foo" => "bar" } - h.replace(j) - h["foo"].must_equal "bar" - end - - it "be able to delete the given key case-sensitively" do - h = Rack::Utils::HeaderHash.new("foo" => "bar") - h.delete("foo") - h["foo"].must_be_nil - h["FOO"].must_be_nil - end - - it "be able to delete the given key case-insensitively" do - h = Rack::Utils::HeaderHash.new("foo" => "bar") - h.delete("FOO") - h["foo"].must_be_nil - h["FOO"].must_be_nil - end - - it "return the deleted value when #delete is called on an existing key" do - h = Rack::Utils::HeaderHash.new("foo" => "bar") - h.delete("Foo").must_equal "bar" - end - - it "return nil when #delete is called on a non-existent key" do - h = Rack::Utils::HeaderHash.new("foo" => "bar") - h.delete("Hello").must_be_nil - end - - it "dups given HeaderHash" do - a = Rack::Utils::HeaderHash.new("foo" => "bar") - b = Rack::Utils::HeaderHash.new(a) - b.object_id.wont_equal a.object_id - b.must_equal a - end - - it "convert Array values to Strings when responding to #each" do - h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"]) - h.each do |k, v| - k.must_equal "foo" - v.must_equal "bar\nbaz" - end - end - - it "not create headers out of thin air" do - h = Rack::Utils::HeaderHash.new - h['foo'] - h['foo'].must_be_nil - h.wont_include 'foo' - end - - it "uses memoized header hash" do - env = {} - headers = Rack::Utils::HeaderHash.new({ 'content-type' => "text/plain", "content-length" => "3" }) - - app = lambda do |env| - [200, headers, []] - end - - app = Rack::ContentLength.new(app) - - response = app.call(env) - assert_same response[1], headers - end - - it "duplicates header hash" do - env = {} - headers = Rack::Utils::HeaderHash.new({ 'content-type' => "text/plain", "content-length" => "3" }) - headers.freeze - - app = lambda do |env| - [200, headers, []] - end - - app = Rack::ContentLength.new(app) - - response = app.call(env) - refute_same response[1], headers + h = Rack::Utils::HeaderHash.new([["Content-MD5","d5ff4e2a0 ..."]]) + h.must_be_kind_of Rack::Headers + h['content-md5'].must_equal "d5ff4e2a0 ..." end end @@ -850,7 +689,7 @@ describe Rack::Utils::Context do test_target1 = proc{|e| e.to_s + ' world' } test_target2 = proc{|e| e.to_i + 2 } test_target3 = proc{|e| nil } - test_target4 = proc{|e| [200, { 'Content-Type' => 'text/plain', 'Content-Length' => '0' }, ['']] } + test_target4 = proc{|e| [200, { 'content-type' => 'text/plain', 'content-length' => '0' }, ['']] } test_app = ContextTest.new test_target4 it "set context correctly" do diff --git a/test/spec_webrick.rb b/test/spec_webrick.rb index 96f86c25..3d689474 100644 --- a/test/spec_webrick.rb +++ b/test/spec_webrick.rb @@ -157,8 +157,8 @@ describe Rack::Handler::WEBrick do Rack::Lint.new(lambda { |req| [ 401, - { "Content-Type" => "text/plain", - "WWW-Authenticate" => "Bar realm=X\nBaz realm=Y" }, + { "content-type" => "text/plain", + "www-authenticate" => "Bar realm=X\nBaz realm=Y" }, [""] ] }) @@ -198,15 +198,15 @@ describe Rack::Handler::WEBrick do Rack::Lint.new(lambda{ |req| [ 200, - { "Transfer-Encoding" => "chunked" }, + { "transfer-encoding" => "chunked" }, ["7\r\nchunked\r\n0\r\n\r\n"] ] }) Net::HTTP.start(@host, @port){ |http| res = http.get("/chunked") - res["Transfer-Encoding"].must_equal "chunked" - res["Content-Length"].must_be_nil + res["transfer-encoding"].must_equal "chunked" + res["content-length"].must_be_nil res.body.must_equal "chunked" } end diff --git a/test/test_request.rb b/test/test_request.rb index 23beecf7..d40169aa 100644 --- a/test/test_request.rb +++ b/test/test_request.rb @@ -16,7 +16,7 @@ class TestRequest minienv.delete_if { |k, v| NOSERIALIZE.any? { |c| v.kind_of?(c) } } body = minienv.to_yaml size = body.bytesize - [status, { "Content-Type" => "text/yaml", "Content-Length" => size.to_s }, [body]] + [status, { "content-type" => "text/yaml", "content-length" => size.to_s }, [body]] end module Helpers @@ -70,7 +70,7 @@ end class StreamingRequest def self.call(env) - [200, { "Content-Type" => "text/plain" }, new] + [200, { "content-type" => "text/plain" }, new] end def each |