From 11e815e9389286883128e69a4269a044c7fc3831 Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Fri, 28 Feb 2014 21:49:45 -0800 Subject: Refactor tests from BaseRackTest into BaseRequestTest --- actionpack/test/dispatch/rack_test.rb | 191 ----------- actionpack/test/dispatch/request_test.rb | 565 +++++++++++++++++++++---------- 2 files changed, 386 insertions(+), 370 deletions(-) delete mode 100644 actionpack/test/dispatch/rack_test.rb (limited to 'actionpack/test/dispatch') diff --git a/actionpack/test/dispatch/rack_test.rb b/actionpack/test/dispatch/rack_test.rb deleted file mode 100644 index ef1964fd19..0000000000 --- a/actionpack/test/dispatch/rack_test.rb +++ /dev/null @@ -1,191 +0,0 @@ -require 'abstract_unit' - -# TODO: Merge these tests into RequestTest - -class BaseRackTest < ActiveSupport::TestCase - def setup - @env = { - "HTTP_MAX_FORWARDS" => "10", - "SERVER_NAME" => "glu.ttono.us", - "FCGI_ROLE" => "RESPONDER", - "AUTH_TYPE" => "Basic", - "HTTP_X_FORWARDED_HOST" => "glu.ttono.us", - "HTTP_ACCEPT_CHARSET" => "UTF-8", - "HTTP_ACCEPT_ENCODING" => "gzip, deflate", - "HTTP_CACHE_CONTROL" => "no-cache, max-age=0", - "HTTP_PRAGMA" => "no-cache", - "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)", - "PATH_INFO" => "/homepage/", - "HTTP_ACCEPT_LANGUAGE" => "en", - "HTTP_NEGOTIATE" => "trans", - "HTTP_HOST" => "glu.ttono.us:8007", - "HTTP_REFERER" => "http://www.google.com/search?q=glu.ttono.us", - "HTTP_FROM" => "googlebot", - "SERVER_PROTOCOL" => "HTTP/1.1", - "REDIRECT_URI" => "/dispatch.fcgi", - "SCRIPT_NAME" => "/dispatch.fcgi", - "SERVER_ADDR" => "207.7.108.53", - "REMOTE_ADDR" => "207.7.108.53", - "REMOTE_HOST" => "google.com", - "REMOTE_IDENT" => "kevin", - "REMOTE_USER" => "kevin", - "SERVER_SOFTWARE" => "lighttpd/1.4.5", - "HTTP_COOKIE" => "_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes", - "HTTP_X_FORWARDED_SERVER" => "glu.ttono.us", - "REQUEST_URI" => "/admin", - "DOCUMENT_ROOT" => "/home/kevinc/sites/typo/public", - "PATH_TRANSLATED" => "/home/kevinc/sites/typo/public/homepage/", - "SERVER_PORT" => "8007", - "QUERY_STRING" => "", - "REMOTE_PORT" => "63137", - "GATEWAY_INTERFACE" => "CGI/1.1", - "HTTP_X_FORWARDED_FOR" => "65.88.180.234", - "HTTP_ACCEPT" => "*/*", - "SCRIPT_FILENAME" => "/home/kevinc/sites/typo/public/dispatch.fcgi", - "REDIRECT_STATUS" => "200", - "REQUEST_METHOD" => "GET" - } - @request = ActionDispatch::Request.new(@env) - # some Nokia phone browsers omit the space after the semicolon separator. - # some developers have grown accustomed to using comma in cookie values. - @alt_cookie_fmt_request = ActionDispatch::Request.new(@env.merge({"HTTP_COOKIE"=>"_session_id=c84ace847,96670c052c6ceb2451fb0f2;is_admin=yes"})) - end - - private - def set_content_data(data) - @request.env['REQUEST_METHOD'] = 'POST' - @request.env['CONTENT_LENGTH'] = data.length - @request.env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded; charset=utf-8' - @request.env['rack.input'] = StringIO.new(data) - end -end - -class RackRequestTest < BaseRackTest - test "proxy request" do - assert_equal 'glu.ttono.us', @request.host_with_port - end - - test "http host" do - @env.delete "HTTP_X_FORWARDED_HOST" - @env['HTTP_HOST'] = "rubyonrails.org:8080" - assert_equal "rubyonrails.org", @request.host - assert_equal "rubyonrails.org:8080", @request.host_with_port - - @env['HTTP_X_FORWARDED_HOST'] = "www.firsthost.org, www.secondhost.org" - assert_equal "www.secondhost.org", @request.host - end - - test "http host with default port overrides server port" do - @env.delete "HTTP_X_FORWARDED_HOST" - @env['HTTP_HOST'] = "rubyonrails.org" - assert_equal "rubyonrails.org", @request.host_with_port - end - - test "host with port defaults to server name if no host headers" do - @env.delete "HTTP_X_FORWARDED_HOST" - @env.delete "HTTP_HOST" - assert_equal "glu.ttono.us:8007", @request.host_with_port - end - - test "host with port falls back to server addr if necessary" do - @env.delete "HTTP_X_FORWARDED_HOST" - @env.delete "HTTP_HOST" - @env.delete "SERVER_NAME" - assert_equal "207.7.108.53", @request.host - assert_equal 8007, @request.port - assert_equal "207.7.108.53:8007", @request.host_with_port - end - - test "host with port if http standard port is specified" do - @env['HTTP_X_FORWARDED_HOST'] = "glu.ttono.us:80" - assert_equal "glu.ttono.us", @request.host_with_port - end - - test "host with port if https standard port is specified" do - @env['HTTP_X_FORWARDED_PROTO'] = "https" - @env['HTTP_X_FORWARDED_HOST'] = "glu.ttono.us:443" - assert_equal "glu.ttono.us", @request.host_with_port - end - - test "host if ipv6 reference" do - @env.delete "HTTP_X_FORWARDED_HOST" - @env['HTTP_HOST'] = "[2001:1234:5678:9abc:def0::dead:beef]" - assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", @request.host - end - - test "host if ipv6 reference with port" do - @env.delete "HTTP_X_FORWARDED_HOST" - @env['HTTP_HOST'] = "[2001:1234:5678:9abc:def0::dead:beef]:8008" - assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", @request.host - end - - test "CGI environment variables" do - assert_equal "Basic", @request.auth_type - assert_equal 0, @request.content_length - assert_equal nil, @request.content_mime_type - assert_equal "CGI/1.1", @request.gateway_interface - assert_equal "*/*", @request.accept - assert_equal "UTF-8", @request.accept_charset - assert_equal "gzip, deflate", @request.accept_encoding - assert_equal "en", @request.accept_language - assert_equal "no-cache, max-age=0", @request.cache_control - assert_equal "googlebot", @request.from - assert_equal "glu.ttono.us", @request.host - assert_equal "trans", @request.negotiate - assert_equal "no-cache", @request.pragma - assert_equal "http://www.google.com/search?q=glu.ttono.us", @request.referer - assert_equal "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)", @request.user_agent - assert_equal "/homepage/", @request.path_info - assert_equal "/home/kevinc/sites/typo/public/homepage/", @request.path_translated - assert_equal "", @request.query_string - assert_equal "207.7.108.53", @request.remote_addr - assert_equal "google.com", @request.remote_host - assert_equal "kevin", @request.remote_ident - assert_equal "kevin", @request.remote_user - assert_equal "GET", @request.request_method - assert_equal "/dispatch.fcgi", @request.script_name - assert_equal "glu.ttono.us", @request.server_name - assert_equal 8007, @request.server_port - assert_equal "HTTP/1.1", @request.server_protocol - assert_equal "lighttpd", @request.server_software - end - - test "cookie syntax resilience" do - cookies = @request.cookies - assert_equal "c84ace84796670c052c6ceb2451fb0f2", cookies["_session_id"], cookies.inspect - assert_equal "yes", cookies["is_admin"], cookies.inspect - - alt_cookies = @alt_cookie_fmt_request.cookies - #assert_equal "c84ace847,96670c052c6ceb2451fb0f2", alt_cookies["_session_id"], alt_cookies.inspect - assert_equal "yes", alt_cookies["is_admin"], alt_cookies.inspect - end -end - -class RackRequestParamsParsingTest < BaseRackTest - test "doesnt break when content type has charset" do - set_content_data 'flamenco=love' - - assert_equal({"flamenco"=> "love"}, @request.request_parameters) - end - - test "doesnt interpret request uri as query string when missing" do - @request.env['REQUEST_URI'] = 'foo' - assert_equal({}, @request.query_parameters) - end -end - -class RackRequestNeedsRewoundTest < BaseRackTest - test "body should be rewound" do - data = 'foo' - @env['rack.input'] = StringIO.new(data) - @env['CONTENT_LENGTH'] = data.length - @env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded; charset=utf-8' - - # Read the request body by parsing params. - request = ActionDispatch::Request.new(@env) - request.request_parameters - - # Should have rewound the body. - assert_equal 0, request.body.pos - end -end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 40e32cb4d3..6e21b4a258 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -1,12 +1,34 @@ require 'abstract_unit' -class RequestTest < ActiveSupport::TestCase +class BaseRequestTest < ActiveSupport::TestCase + def setup + @env = { + :ip_spoofing_check => true, + :tld_length => 1, + "rack.input" => "foo" + } + end def url_for(options = {}) options = { host: 'www.example.com' }.merge!(options) ActionDispatch::Http::URL.url_for(options) end + protected + def stub_request(env = {}) + ip_spoofing_check = env.key?(:ip_spoofing_check) ? env.delete(:ip_spoofing_check) : true + @trusted_proxies ||= nil + ip_app = ActionDispatch::RemoteIp.new(Proc.new { }, ip_spoofing_check, @trusted_proxies) + tld_length = env.key?(:tld_length) ? env.delete(:tld_length) : 1 + ip_app.call(env) + ActionDispatch::Http::URL.tld_length = tld_length + + env = @env.merge(env) + ActionDispatch::Request.new(env) + end +end + +class RequestUrlFor < BaseRequestTest test "url_for class method" do e = assert_raise(ArgumentError) { url_for(:host => nil) } assert_match(/Please provide the :host parameter/, e.message) @@ -31,7 +53,9 @@ class RequestTest < ActiveSupport::TestCase assert_equal 'http://www.example.com?params=', url_for(:params => '') assert_equal 'http://www.example.com?params=1', url_for(:params => 1) end +end +class RequestIP < BaseRequestTest test "remote ip" do request = stub_request 'REMOTE_ADDR' => '1.2.3.4' assert_equal '1.2.3.4', request.remote_ip @@ -220,10 +244,12 @@ class RequestTest < ActiveSupport::TestCase end test "remote ip middleware not present still returns an IP" do - request = ActionDispatch::Request.new({'REMOTE_ADDR' => '127.0.0.1'}) + request = stub_request('REMOTE_ADDR' => '127.0.0.1') assert_equal '127.0.0.1', request.remote_ip end +end +class RequestDomain < BaseRequestTest test "domains" do request = stub_request 'HTTP_HOST' => 'www.rubyonrails.org' assert_equal "rubyonrails.org", request.domain @@ -281,7 +307,9 @@ class RequestTest < ActiveSupport::TestCase assert_equal [], request.subdomains assert_equal "", request.subdomain end +end +class RequestPort < BaseRequestTest test "standard_port" do request = stub_request assert_equal 80, request.standard_port @@ -323,7 +351,9 @@ class RequestTest < ActiveSupport::TestCase request = stub_request 'HTTP_HOST' => 'www.example.org:8080' assert_equal ':8080', request.port_string end +end +class RequestPath < BaseRequestTest test "full path" do request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/path/of/some/uri', 'QUERY_STRING' => 'mapped=1' assert_equal "/path/of/some/uri?mapped=1", request.fullpath @@ -354,6 +384,32 @@ class RequestTest < ActiveSupport::TestCase assert_equal "/of/some/uri", request.path_info end + test "original_fullpath returns ORIGINAL_FULLPATH" do + request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar") + + path = request.original_fullpath + assert_equal "/foo?bar", path + end + + test "original_url returns url built using ORIGINAL_FULLPATH" do + request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar", + 'HTTP_HOST' => "example.org", + 'rack.url_scheme' => "http") + + url = request.original_url + assert_equal "http://example.org/foo?bar", url + end + + test "original_fullpath returns fullpath if ORIGINAL_FULLPATH is not present" do + request = stub_request('PATH_INFO' => "/foo", + 'QUERY_STRING' => "bar") + + path = request.original_fullpath + assert_equal "/foo?bar", path + end +end + +class RequestHost < BaseRequestTest test "host with default port" do request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80' assert_equal "rubyonrails.org", request.host_with_port @@ -364,15 +420,174 @@ class RequestTest < ActiveSupport::TestCase assert_equal "rubyonrails.org:81", request.host_with_port end - test "server software" do - request = stub_request - assert_equal nil, request.server_software + test "proxy request" do + request = stub_request 'HTTP_HOST' => 'glu.ttono.us:80' + assert_equal "glu.ttono.us", request.host_with_port + end + + test "http host" do + request = stub_request 'HTTP_HOST' => "rubyonrails.org:8080" + assert_equal "rubyonrails.org", request.host + assert_equal "rubyonrails.org:8080", request.host_with_port + + request = stub_request 'HTTP_X_FORWARDED_HOST' => "www.firsthost.org, www.secondhost.org" + assert_equal "www.secondhost.org", request.host + end + + test "http host with default port overrides server port" do + request = stub_request 'HTTP_HOST' => "rubyonrails.org" + assert_equal "rubyonrails.org", request.host_with_port + end + + test "host with port if http standard port is specified" do + request = stub_request 'HTTP_X_FORWARDED_HOST' => "glu.ttono.us:80" + assert_equal "glu.ttono.us", request.host_with_port + end + + test "host with port if https standard port is specified" do + request = stub_request( + 'HTTP_X_FORWARDED_PROTO' => "https", + 'HTTP_X_FORWARDED_HOST' => "glu.ttono.us:443" + ) + assert_equal "glu.ttono.us", request.host_with_port + end + + test "host if ipv6 reference" do + request = stub_request 'HTTP_HOST' => "[2001:1234:5678:9abc:def0::dead:beef]" + assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", request.host + end + + test "host if ipv6 reference with port" do + request = stub_request 'HTTP_HOST' => "[2001:1234:5678:9abc:def0::dead:beef]:8008" + assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", request.host + end +end + +class RequestCGI < BaseRequestTest + test "CGI environment variables" do + request = stub_request( + "AUTH_TYPE" => "Basic", + "GATEWAY_INTERFACE" => "CGI/1.1", + "HTTP_ACCEPT" => "*/*", + "HTTP_ACCEPT_CHARSET" => "UTF-8", + "HTTP_ACCEPT_ENCODING" => "gzip, deflate", + "HTTP_ACCEPT_LANGUAGE" => "en", + "HTTP_CACHE_CONTROL" => "no-cache, max-age=0", + "HTTP_FROM" => "googlebot", + "HTTP_HOST" => "glu.ttono.us:8007", + "HTTP_NEGOTIATE" => "trans", + "HTTP_PRAGMA" => "no-cache", + "HTTP_REFERER" => "http://www.google.com/search?q=glu.ttono.us", + "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)", + "PATH_INFO" => "/homepage/", + "PATH_TRANSLATED" => "/home/kevinc/sites/typo/public/homepage/", + "QUERY_STRING" => "", + "REMOTE_ADDR" => "207.7.108.53", + "REMOTE_HOST" => "google.com", + "REMOTE_IDENT" => "kevin", + "REMOTE_USER" => "kevin", + "REQUEST_METHOD" => "GET", + "SCRIPT_NAME" => "/dispatch.fcgi", + "SERVER_NAME" => "glu.ttono.us", + "SERVER_PORT" => "8007", + "SERVER_PROTOCOL" => "HTTP/1.1", + "SERVER_SOFTWARE" => "lighttpd/1.4.5", + ) + + assert_equal "Basic", request.auth_type + assert_equal 0, request.content_length + assert_equal nil, request.content_mime_type + assert_equal "CGI/1.1", request.gateway_interface + assert_equal "*/*", request.accept + assert_equal "UTF-8", request.accept_charset + assert_equal "gzip, deflate", request.accept_encoding + assert_equal "en", request.accept_language + assert_equal "no-cache, max-age=0", request.cache_control + assert_equal "googlebot", request.from + assert_equal "glu.ttono.us", request.host + assert_equal "trans", request.negotiate + assert_equal "no-cache", request.pragma + assert_equal "http://www.google.com/search?q=glu.ttono.us", request.referer + assert_equal "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)", request.user_agent + assert_equal "/homepage/", request.path_info + assert_equal "/home/kevinc/sites/typo/public/homepage/", request.path_translated + assert_equal "", request.query_string + assert_equal "207.7.108.53", request.remote_addr + assert_equal "google.com", request.remote_host + assert_equal "kevin", request.remote_ident + assert_equal "kevin", request.remote_user + assert_equal "GET", request.request_method + assert_equal "/dispatch.fcgi", request.script_name + assert_equal "glu.ttono.us", request.server_name + assert_equal 8007, request.server_port + assert_equal "HTTP/1.1", request.server_protocol + assert_equal "lighttpd", request.server_software + end +end + +class RequestCookie < BaseRequestTest + test "cookie syntax resilience" do + request = stub_request("HTTP_COOKIE" => "_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes") + assert_equal "c84ace84796670c052c6ceb2451fb0f2", request.cookies["_session_id"], request.cookies.inspect + assert_equal "yes", request.cookies["is_admin"], request.cookies.inspect + + # some Nokia phone browsers omit the space after the semicolon separator. + # some developers have grown accustomed to using comma in cookie values. + request = stub_request("HTTP_COOKIE"=>"_session_id=c84ace847,96670c052c6ceb2451fb0f2;is_admin=yes") + assert_equal "c84ace847", request.cookies["_session_id"], request.cookies.inspect + assert_equal "yes", request.cookies["is_admin"], request.cookies.inspect + end +end + +class RequestParamsParsing < BaseRequestTest + test "doesnt break when content type has charset" do + request = stub_request( + 'REQUEST_METHOD' => 'POST', + 'CONTENT_LENGTH' => "flamenco=love".length, + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded; charset=utf-8', + 'rack.input' => StringIO.new("flamenco=love") + ) + + assert_equal({"flamenco"=> "love"}, request.request_parameters) + end + + test "doesnt interpret request uri as query string when missing" do + request = stub_request('REQUEST_URI' => 'foo') + assert_equal({}, request.query_parameters) + end +end - request = stub_request 'SERVER_SOFTWARE' => 'Apache3.422' - assert_equal 'apache', request.server_software +class RequestRewind < BaseRequestTest + test "body should be rewound" do + data = 'rewind' + env = { + 'rack.input' => StringIO.new(data), + 'CONTENT_LENGTH' => data.length, + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded; charset=utf-8' + } + + # Read the request body by parsing params. + request = stub_request(env) + request.request_parameters + + # Should have rewound the body. + assert_equal 0, request.body.pos + end + + test "raw_post rewinds rack.input if RAW_POST_DATA is nil" do + request = stub_request( + 'rack.input' => StringIO.new("raw"), + 'CONTENT_LENGTH' => 3 + ) + assert_equal "raw", request.raw_post + assert_equal "raw", request.env['rack.input'].read + end +end - request = stub_request 'SERVER_SOFTWARE' => 'lighttpd(1.1.4)' - assert_equal 'lighttpd', request.server_software +class RequestProtocol < BaseRequestTest + test "server software" do + assert_equal 'lighttpd', stub_request('SERVER_SOFTWARE' => 'lighttpd/1.4.5').server_software + assert_equal 'apache', stub_request('SERVER_SOFTWARE' => 'Apache3.422').server_software end test "xml http request" do @@ -391,19 +606,12 @@ class RequestTest < ActiveSupport::TestCase end test "reports ssl" do - request = stub_request - assert !request.ssl? - - request = stub_request 'HTTPS' => 'on' - assert request.ssl? + assert !stub_request.ssl? + assert stub_request('HTTPS' => 'on').ssl? end test "reports ssl when proxied via lighttpd" do - request = stub_request - assert !request.ssl? - - request = stub_request 'HTTP_X_FORWARDED_PROTO' => 'https' - assert request.ssl? + assert stub_request('HTTP_X_FORWARDED_PROTO' => 'https').ssl? end test "scheme returns https when proxied" do @@ -411,63 +619,72 @@ class RequestTest < ActiveSupport::TestCase assert !request.ssl? assert_equal 'http', request.scheme - request = stub_request 'rack.url_scheme' => 'http', 'HTTP_X_FORWARDED_PROTO' => 'https' + request = stub_request( + 'rack.url_scheme' => 'http', + 'HTTP_X_FORWARDED_PROTO' => 'https' + ) assert request.ssl? assert_equal 'https', request.scheme end +end - test "String request methods" do - [:get, :post, :patch, :put, :delete].each do |method| - request = stub_request 'REQUEST_METHOD' => method.to_s.upcase - assert_equal method.to_s.upcase, request.method - end - end +class RequestMethod < BaseRequestTest + test "request methods" do + [:post, :get, :patch, :put, :delete].each do |method| + request = stub_request('REQUEST_METHOD' => method.to_s.upcase) - test "Symbol forms of request methods via method_symbol" do - [:get, :post, :patch, :put, :delete].each do |method| - request = stub_request 'REQUEST_METHOD' => method.to_s.upcase + assert_equal method.to_s.upcase, request.method assert_equal method, request.method_symbol end end test "invalid http method raises exception" do assert_raise(ActionController::UnknownHttpMethod) do - request = stub_request 'REQUEST_METHOD' => 'RANDOM_METHOD' - request.request_method + stub_request('REQUEST_METHOD' => 'RANDOM_METHOD').request_method end end test "allow method hacking on post" do %w(GET OPTIONS PATCH PUT POST DELETE).each do |method| - request = stub_request "REQUEST_METHOD" => method.to_s.upcase + request = stub_request 'REQUEST_METHOD' => method.to_s.upcase + assert_equal(method == "HEAD" ? "GET" : method, request.method) end end test "invalid method hacking on post raises exception" do assert_raise(ActionController::UnknownHttpMethod) do - request = stub_request "REQUEST_METHOD" => "_RANDOM_METHOD" - request.request_method + stub_request('REQUEST_METHOD' => '_RANDOM_METHOD').request_method end end test "restrict method hacking" do [:get, :patch, :put, :delete].each do |method| - request = stub_request 'REQUEST_METHOD' => method.to_s.upcase, - 'action_dispatch.request.request_parameters' => { :_method => 'put' } + request = stub_request( + 'action_dispatch.request.request_parameters' => { :_method => 'put' }, + 'REQUEST_METHOD' => method.to_s.upcase + ) + assert_equal method.to_s.upcase, request.method end end test "post masquerading as patch" do - request = stub_request 'REQUEST_METHOD' => 'PATCH', "rack.methodoverride.original_method" => "POST" + request = stub_request( + 'REQUEST_METHOD' => 'PATCH', + "rack.methodoverride.original_method" => "POST" + ) + assert_equal "POST", request.method assert_equal "PATCH", request.request_method assert request.patch? end test "post masquerading as put" do - request = stub_request 'REQUEST_METHOD' => 'PUT', "rack.methodoverride.original_method" => "POST" + request = stub_request( + 'REQUEST_METHOD' => 'PUT', + "rack.methodoverride.original_method" => "POST" + ) assert_equal "POST", request.method assert_equal "PUT", request.request_method assert request.put? @@ -493,7 +710,9 @@ class RequestTest < ActiveSupport::TestCase end end end +end +class RequestFormat < BaseRequestTest test "xml format" do request = stub_request request.expects(:parameters).at_least_once.returns({ :format => 'xml' }) @@ -513,109 +732,55 @@ class RequestTest < ActiveSupport::TestCase end test "XMLHttpRequest" do - request = stub_request 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest', - 'HTTP_ACCEPT' => - [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(",") + request = stub_request( + 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest', + 'HTTP_ACCEPT' => [Mime::JS, Mime::HTML, Mime::XML, "text/xml", Mime::ALL].join(",") + ) request.expects(:parameters).at_least_once.returns({}) assert request.xhr? assert_equal Mime::JS, request.format end - test "content type" do - request = stub_request 'CONTENT_TYPE' => 'text/html' - assert_equal Mime::HTML, request.content_mime_type - end - - test "can override format with parameter" do + test "can override format with parameter negative" do request = stub_request request.expects(:parameters).at_least_once.returns({ :format => :txt }) assert !request.format.xml? + end + test "can override format with parameter positive" do request = stub_request request.expects(:parameters).at_least_once.returns({ :format => :xml }) assert request.format.xml? end - test "no content type" do - request = stub_request - assert_equal nil, request.content_mime_type - end - - test "content type is XML" do - request = stub_request 'CONTENT_TYPE' => 'application/xml' - assert_equal Mime::XML, request.content_mime_type - end - - test "content type with charset" do - request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8' - assert_equal Mime::XML, request.content_mime_type - end - - test "user agent" do - request = stub_request 'HTTP_USER_AGENT' => 'TestAgent' - assert_equal 'TestAgent', request.user_agent - end - - test "parameters" do - request = stub_request - request.stubs(:request_parameters).returns({ "foo" => 1 }) - request.stubs(:query_parameters).returns({ "bar" => 2 }) - - assert_equal({"foo" => 1, "bar" => 2}, request.parameters) - assert_equal({"foo" => 1}, request.request_parameters) - assert_equal({"bar" => 2}, request.query_parameters) - end - - test "parameters still accessible after rack parse error" do - mock_rack_env = { "QUERY_STRING" => "x[y]=1&x[y][][w]=2", "rack.input" => "foo" } - request = nil - request = stub_request(mock_rack_env) - - assert_raises(ActionController::BadRequest) do - # rack will raise a TypeError when parsing this query string - request.parameters - end - - assert_equal({}, request.parameters) - end - - test "we have access to the original exception" do - mock_rack_env = { "QUERY_STRING" => "x[y]=1&x[y][][w]=2", "rack.input" => "foo" } - request = nil - request = stub_request(mock_rack_env) - - e = assert_raises(ActionController::BadRequest) do - # rack will raise a TypeError when parsing this query string - request.parameters - end - - assert e.original_exception - assert_equal e.original_exception.backtrace, e.backtrace - end - - test "formats with accept header" do + test "formats text/html with accept header" do request = stub_request 'HTTP_ACCEPT' => 'text/html' - request.expects(:parameters).at_least_once.returns({}) assert_equal [Mime::HTML], request.formats + end + test "formats blank with accept header" do request = stub_request 'HTTP_ACCEPT' => '' - request.expects(:parameters).at_least_once.returns({}) assert_equal [Mime::HTML], request.formats + end - request = stub_request 'HTTP_ACCEPT' => '', - 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" - request.expects(:parameters).at_least_once.returns({}) + test "formats XMLHttpRequest with accept header" do + request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" assert_equal [Mime::JS], request.formats + end - request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8', - 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" - request.expects(:parameters).at_least_once.returns({}) + test "formats application/xml with accept header" do + request = stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8', + 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest") assert_equal [Mime::XML], request.formats + end + test "formats format:text with accept header" do request = stub_request request.expects(:parameters).at_least_once.returns({ :format => :txt }) assert_equal [Mime::TEXT], request.formats + end + test "formats format:unknown with accept header" do request = stub_request request.expects(:parameters).at_least_once.returns({ :format => :unknown }) assert_instance_of Mime::NullType, request.format @@ -669,30 +834,87 @@ class RequestTest < ActiveSupport::TestCase ActionDispatch::Request.ignore_accept_header = false end end +end - test "negotiate_mime" do - request = stub_request 'HTTP_ACCEPT' => 'text/html', - 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" +class RequestMimeType < BaseRequestTest + test "content type" do + assert_equal Mime::HTML, stub_request('CONTENT_TYPE' => 'text/html').content_mime_type + end - request.expects(:parameters).at_least_once.returns({}) + test "no content type" do + assert_equal nil, stub_request.content_mime_type + end + + test "content type is XML" do + assert_equal Mime::XML, stub_request('CONTENT_TYPE' => 'application/xml').content_mime_type + end + + test "content type with charset" do + assert_equal Mime::XML, stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8').content_mime_type + end + + test "user agent" do + assert_equal 'TestAgent', stub_request('HTTP_USER_AGENT' => 'TestAgent').user_agent + end + + test "negotiate_mime" do + request = stub_request( + 'HTTP_ACCEPT' => 'text/html', + 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" + ) assert_equal nil, request.negotiate_mime([Mime::XML, Mime::JSON]) assert_equal Mime::HTML, request.negotiate_mime([Mime::XML, Mime::HTML]) assert_equal Mime::HTML, request.negotiate_mime([Mime::XML, Mime::ALL]) + end + + test "negotiate_mime with content_type" do + request = stub_request( + 'CONTENT_TYPE' => 'application/xml; charset=UTF-8', + 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" + ) - request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8', - 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" - request.expects(:parameters).at_least_once.returns({}) assert_equal Mime::XML, request.negotiate_mime([Mime::XML, Mime::CSV]) end +end - test "raw_post rewinds rack.input if RAW_POST_DATA is nil" do - request = stub_request('rack.input' => StringIO.new("foo"), - 'CONTENT_LENGTH' => 3) - assert_equal "foo", request.raw_post - assert_equal "foo", request.env['rack.input'].read +class RequestParameters < BaseRequestTest + test "parameters" do + request = stub_request + request.expects(:request_parameters).at_least_once.returns({ "foo" => 1 }) + request.expects(:query_parameters).at_least_once.returns({ "bar" => 2 }) + + assert_equal({"foo" => 1, "bar" => 2}, request.parameters) + assert_equal({"foo" => 1}, request.request_parameters) + assert_equal({"bar" => 2}, request.query_parameters) + end + + test "parameters still accessible after rack parse error" do + request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2") + + assert_raises(ActionController::BadRequest) do + # rack will raise a TypeError when parsing this query string + request.parameters + end + + assert_equal({}, request.parameters) end + test "we have access to the original exception" do + request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2") + + e = assert_raises(ActionController::BadRequest) do + # rack will raise a TypeError when parsing this query string + request.parameters + end + + assert e.original_exception + assert_equal e.original_exception.backtrace, e.backtrace + end +end + + +class RequestParameterFilter < BaseRequestTest test "process parameter filter" do test_hashes = [ [{'foo'=>'bar'},{'foo'=>'bar'},%w'food'], @@ -721,9 +943,14 @@ class RequestTest < ActiveSupport::TestCase end test "filtered_parameters returns params filtered" do - request = stub_request('action_dispatch.request.parameters' => - { 'lifo' => 'Pratik', 'amount' => '420', 'step' => '1' }, - 'action_dispatch.parameter_filter' => [:lifo, :amount]) + request = stub_request( + 'action_dispatch.request.parameters' => { + 'lifo' => 'Pratik', + 'amount' => '420', + 'step' => '1' + }, + 'action_dispatch.parameter_filter' => [:lifo, :amount] + ) params = request.filtered_parameters assert_equal "[FILTERED]", params["lifo"] @@ -732,10 +959,14 @@ class RequestTest < ActiveSupport::TestCase end test "filtered_env filters env as a whole" do - request = stub_request('action_dispatch.request.parameters' => - { 'amount' => '420', 'step' => '1' }, "RAW_POST_DATA" => "yada yada", - 'action_dispatch.parameter_filter' => [:lifo, :amount]) - + request = stub_request( + 'action_dispatch.request.parameters' => { + 'amount' => '420', + 'step' => '1' + }, + "RAW_POST_DATA" => "yada yada", + 'action_dispatch.parameter_filter' => [:lifo, :amount] + ) request = stub_request(request.filtered_env) assert_equal "[FILTERED]", request.raw_post @@ -745,9 +976,11 @@ class RequestTest < ActiveSupport::TestCase test "filtered_path returns path with filtered query string" do %w(; &).each do |sep| - request = stub_request('QUERY_STRING' => %w(username=sikachu secret=bd4f21f api_key=b1bc3b3cd352f68d79d7).join(sep), + request = stub_request( + 'QUERY_STRING' => %w(username=sikachu secret=bd4f21f api_key=b1bc3b3cd352f68d79d7).join(sep), 'PATH_INFO' => '/authenticate', - 'action_dispatch.parameter_filter' => [:secret, :api_key]) + 'action_dispatch.parameter_filter' => [:secret, :api_key] + ) path = request.filtered_path assert_equal %w(/authenticate?username=sikachu secret=[FILTERED] api_key=[FILTERED]).join(sep), path @@ -755,56 +988,40 @@ class RequestTest < ActiveSupport::TestCase end test "filtered_path should not unescape a genuine '[FILTERED]' value" do - request = stub_request('QUERY_STRING' => "secret=bd4f21f&genuine=%5BFILTERED%5D", + request = stub_request( + 'QUERY_STRING' => "secret=bd4f21f&genuine=%5BFILTERED%5D", 'PATH_INFO' => '/authenticate', - 'action_dispatch.parameter_filter' => [:secret]) + 'action_dispatch.parameter_filter' => [:secret] + ) path = request.filtered_path - assert_equal "/authenticate?secret=[FILTERED]&genuine=%5BFILTERED%5D", path + assert_equal request.script_name + "/authenticate?secret=[FILTERED]&genuine=%5BFILTERED%5D", path end test "filtered_path should preserve duplication of keys in query string" do - request = stub_request('QUERY_STRING' => "username=sikachu&secret=bd4f21f&username=fxn", + request = stub_request( + 'QUERY_STRING' => "username=sikachu&secret=bd4f21f&username=fxn", 'PATH_INFO' => '/authenticate', - 'action_dispatch.parameter_filter' => [:secret]) + 'action_dispatch.parameter_filter' => [:secret] + ) path = request.filtered_path - assert_equal "/authenticate?username=sikachu&secret=[FILTERED]&username=fxn", path + assert_equal request.script_name + "/authenticate?username=sikachu&secret=[FILTERED]&username=fxn", path end test "filtered_path should ignore searchparts" do - request = stub_request('QUERY_STRING' => "secret", + request = stub_request( + 'QUERY_STRING' => "secret", 'PATH_INFO' => '/authenticate', - 'action_dispatch.parameter_filter' => [:secret]) + 'action_dispatch.parameter_filter' => [:secret] + ) path = request.filtered_path - assert_equal "/authenticate?secret", path - end - - test "original_fullpath returns ORIGINAL_FULLPATH" do - request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar") - - path = request.original_fullpath - assert_equal "/foo?bar", path - end - - test "original_url returns url built using ORIGINAL_FULLPATH" do - request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar", - 'HTTP_HOST' => "example.org", - 'rack.url_scheme' => "http") - - url = request.original_url - assert_equal "http://example.org/foo?bar", url - end - - test "original_fullpath returns fullpath if ORIGINAL_FULLPATH is not present" do - request = stub_request('PATH_INFO' => "/foo", - 'QUERY_STRING' => "bar") - - path = request.original_fullpath - assert_equal "/foo?bar", path + assert_equal request.script_name + "/authenticate?secret", path end +end +class RequestEtag < BaseRequestTest test "if_none_match_etags none" do request = stub_request @@ -843,7 +1060,9 @@ class RequestTest < ActiveSupport::TestCase assert request.etag_matches?(etag), etag end end +end +class RequestVarient < BaseRequestTest test "setting variant" do request = stub_request @@ -868,16 +1087,4 @@ class RequestTest < ActiveSupport::TestCase request.variant = "mobile" end end - -protected - - def stub_request(env = {}) - ip_spoofing_check = env.key?(:ip_spoofing_check) ? env.delete(:ip_spoofing_check) : true - @trusted_proxies ||= nil - ip_app = ActionDispatch::RemoteIp.new(Proc.new { }, ip_spoofing_check, @trusted_proxies) - tld_length = env.key?(:tld_length) ? env.delete(:tld_length) : 1 - ip_app.call(env) - ActionDispatch::Http::URL.tld_length = tld_length - ActionDispatch::Request.new(env) - end end -- cgit v1.2.3 From ed88a601f7b37de0f89b64249aaeed884faed836 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Fri, 28 Feb 2014 19:39:22 -0500 Subject: Do note remove `Content-Type` when `render :body` `render :body` should just not set the `Content-Type` header. By removing the header, it breaks the compatibility with other parts. After this commit, `render :body` will returns `text/html` content type, sets by default from `ActionDispatch::Response`, and it will preserve the overridden content type if you override it. Fixes #14197, #14238 This partially reverts commit 3047376870d4a7adc7ff15c3cb4852e073c8f1da. --- actionpack/test/dispatch/response_test.rb | 8 -------- 1 file changed, 8 deletions(-) (limited to 'actionpack/test/dispatch') diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 1360ede3f8..959a3bc5cd 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -235,14 +235,6 @@ class ResponseTest < ActiveSupport::TestCase assert_equal @response.body, body.each.to_a.join end end - - test "does not add default content-type if Content-Type is none" do - resp = ActionDispatch::Response.new.tap { |response| - response.no_content_type = true - } - - assert_not resp.headers.has_key?('Content-Type') - end end class ResponseIntegrationTest < ActionDispatch::IntegrationTest -- cgit v1.2.3 From dcc91a04a177466516dac12abc358c590743fa71 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sun, 2 Mar 2014 20:19:04 +0200 Subject: Only use shallow nested scope when depth is > 1 By tracking the depth of resource nesting we can push the need for nested shallow scoping to only those routes that are nested more than one deep. This allows us to keep the fix for #12498 and fix the regression in #14224. Fixes #14224. --- actionpack/test/dispatch/routing_test.rb | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'actionpack/test/dispatch') diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 1fa2cc6cf2..8dad3bcbb3 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -3033,6 +3033,66 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/admin/posts/1/comments', admin_post_comments_path('1') end + def test_shallow_path_and_prefix_are_not_added_to_non_shallow_routes + draw do + scope shallow_path: 'projects', shallow_prefix: 'project' do + resources :projects do + resources :files, controller: 'project_files', shallow: true + end + end + end + + get '/projects' + assert_equal 'projects#index', @response.body + assert_equal '/projects', projects_path + + get '/projects/new' + assert_equal 'projects#new', @response.body + assert_equal '/projects/new', new_project_path + + post '/projects' + assert_equal 'projects#create', @response.body + + get '/projects/1' + assert_equal 'projects#show', @response.body + assert_equal '/projects/1', project_path('1') + + get '/projects/1/edit' + assert_equal 'projects#edit', @response.body + assert_equal '/projects/1/edit', edit_project_path('1') + + patch '/projects/1' + assert_equal 'projects#update', @response.body + + delete '/projects/1' + assert_equal 'projects#destroy', @response.body + + get '/projects/1/files' + assert_equal 'project_files#index', @response.body + assert_equal '/projects/1/files', project_files_path('1') + + get '/projects/1/files/new' + assert_equal 'project_files#new', @response.body + assert_equal '/projects/1/files/new', new_project_file_path('1') + + post '/projects/1/files' + assert_equal 'project_files#create', @response.body + + get '/projects/files/2' + assert_equal 'project_files#show', @response.body + assert_equal '/projects/files/2', project_file_path('2') + + get '/projects/files/2/edit' + assert_equal 'project_files#edit', @response.body + assert_equal '/projects/files/2/edit', edit_project_file_path('2') + + patch '/projects/files/2' + assert_equal 'project_files#update', @response.body + + delete '/projects/files/2' + assert_equal 'project_files#destroy', @response.body + end + private def draw(&block) -- cgit v1.2.3 From 8711086f5a2e73cd068434a5fafef258ba9f4fe1 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Mon, 3 Mar 2014 20:19:17 +0200 Subject: Pull namespace defaults out of the options hash If a developer has specified either :path or :as in the options hash then these should be used as the defaults for :shallow_path and :shallow_prefix. Fixes #14241. --- actionpack/test/dispatch/routing_test.rb | 130 +++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) (limited to 'actionpack/test/dispatch') diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 8dad3bcbb3..e51ece1b2e 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -1031,6 +1031,136 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'users/home#index', @response.body end + def test_namespaced_shallow_routes_with_module_option + draw do + namespace :foo, module: 'bar' do + resources :posts, only: [:index, :show] do + resources :comments, only: [:index, :show], shallow: true + end + end + end + + get '/foo/posts' + assert_equal '/foo/posts', foo_posts_path + assert_equal 'bar/posts#index', @response.body + + get '/foo/posts/1' + assert_equal '/foo/posts/1', foo_post_path('1') + assert_equal 'bar/posts#show', @response.body + + get '/foo/posts/1/comments' + assert_equal '/foo/posts/1/comments', foo_post_comments_path('1') + assert_equal 'bar/comments#index', @response.body + + get '/foo/comments/2' + assert_equal '/foo/comments/2', foo_comment_path('2') + assert_equal 'bar/comments#show', @response.body + end + + def test_namespaced_shallow_routes_with_path_option + draw do + namespace :foo, path: 'bar' do + resources :posts, only: [:index, :show] do + resources :comments, only: [:index, :show], shallow: true + end + end + end + + get '/bar/posts' + assert_equal '/bar/posts', foo_posts_path + assert_equal 'foo/posts#index', @response.body + + get '/bar/posts/1' + assert_equal '/bar/posts/1', foo_post_path('1') + assert_equal 'foo/posts#show', @response.body + + get '/bar/posts/1/comments' + assert_equal '/bar/posts/1/comments', foo_post_comments_path('1') + assert_equal 'foo/comments#index', @response.body + + get '/bar/comments/2' + assert_equal '/bar/comments/2', foo_comment_path('2') + assert_equal 'foo/comments#show', @response.body + end + + def test_namespaced_shallow_routes_with_as_option + draw do + namespace :foo, as: 'bar' do + resources :posts, only: [:index, :show] do + resources :comments, only: [:index, :show], shallow: true + end + end + end + + get '/foo/posts' + assert_equal '/foo/posts', bar_posts_path + assert_equal 'foo/posts#index', @response.body + + get '/foo/posts/1' + assert_equal '/foo/posts/1', bar_post_path('1') + assert_equal 'foo/posts#show', @response.body + + get '/foo/posts/1/comments' + assert_equal '/foo/posts/1/comments', bar_post_comments_path('1') + assert_equal 'foo/comments#index', @response.body + + get '/foo/comments/2' + assert_equal '/foo/comments/2', bar_comment_path('2') + assert_equal 'foo/comments#show', @response.body + end + + def test_namespaced_shallow_routes_with_shallow_path_option + draw do + namespace :foo, shallow_path: 'bar' do + resources :posts, only: [:index, :show] do + resources :comments, only: [:index, :show], shallow: true + end + end + end + + get '/foo/posts' + assert_equal '/foo/posts', foo_posts_path + assert_equal 'foo/posts#index', @response.body + + get '/foo/posts/1' + assert_equal '/foo/posts/1', foo_post_path('1') + assert_equal 'foo/posts#show', @response.body + + get '/foo/posts/1/comments' + assert_equal '/foo/posts/1/comments', foo_post_comments_path('1') + assert_equal 'foo/comments#index', @response.body + + get '/bar/comments/2' + assert_equal '/bar/comments/2', foo_comment_path('2') + assert_equal 'foo/comments#show', @response.body + end + + def test_namespaced_shallow_routes_with_shallow_prefix_option + draw do + namespace :foo, shallow_prefix: 'bar' do + resources :posts, only: [:index, :show] do + resources :comments, only: [:index, :show], shallow: true + end + end + end + + get '/foo/posts' + assert_equal '/foo/posts', foo_posts_path + assert_equal 'foo/posts#index', @response.body + + get '/foo/posts/1' + assert_equal '/foo/posts/1', foo_post_path('1') + assert_equal 'foo/posts#show', @response.body + + get '/foo/posts/1/comments' + assert_equal '/foo/posts/1/comments', foo_post_comments_path('1') + assert_equal 'foo/comments#index', @response.body + + get '/foo/comments/2' + assert_equal '/foo/comments/2', bar_comment_path('2') + assert_equal 'foo/comments#show', @response.body + end + def test_namespace_containing_numbers draw do namespace :v2 do -- cgit v1.2.3 From af4c9b78ff1c967cc1aaef14d34205ef92db8134 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sat, 8 Mar 2014 19:49:11 +0000 Subject: Copy shallow options from normal options when using scope If the options :shallow_prefix and :shallow_path are not set in the scope options then copy them from the normal :as and :path options if they are set. --- actionpack/test/dispatch/routing_test.rb | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'actionpack/test/dispatch') diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index e51ece1b2e..a47050adce 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -3223,6 +3223,54 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'project_files#destroy', @response.body end + def test_scope_path_is_copied_to_shallow_path + draw do + scope path: 'foo' do + resources :posts do + resources :comments, shallow: true + end + end + end + + assert_equal '/foo/comments/1', comment_path('1') + end + + def test_scope_as_is_copied_to_shallow_prefix + draw do + scope as: 'foo' do + resources :posts do + resources :comments, shallow: true + end + end + end + + assert_equal '/comments/1', foo_comment_path('1') + end + + def test_scope_shallow_prefix_is_not_overwritten_by_as + draw do + scope as: 'foo', shallow_prefix: 'bar' do + resources :posts do + resources :comments, shallow: true + end + end + end + + assert_equal '/comments/1', bar_comment_path('1') + end + + def test_scope_shallow_path_is_not_overwritten_by_path + draw do + scope path: 'foo', shallow_path: 'bar' do + resources :posts do + resources :comments, shallow: true + end + end + end + + assert_equal '/bar/comments/1', comment_path('1') + end + private def draw(&block) -- cgit v1.2.3 From 77a09218f697676f8a05f06eeb5c89a26419d489 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 12 Mar 2014 16:07:04 -0700 Subject: only write the jar if the response isn't committed when streaming responses, we need to make sure the cookie jar is written to the headers before returning up the stack. This commit introduces a new method on the response object that writes the cookie jar to the headers as the response is committed. The middleware and test framework will not write the cookie headers if the response has already been committed. fixes #14352 --- actionpack/test/dispatch/live_response_test.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'actionpack/test/dispatch') diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb index e0cfb73acf..336fdd569b 100644 --- a/actionpack/test/dispatch/live_response_test.rb +++ b/actionpack/test/dispatch/live_response_test.rb @@ -6,6 +6,7 @@ module ActionController class ResponseTest < ActiveSupport::TestCase def setup @response = Live::Response.new + @response.request = ActionDispatch::Request.new({}) #yolo end def test_header_merge -- cgit v1.2.3 From 3df07d093a1e4207caa63fd2e3b67599211f5800 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 12 Mar 2014 17:40:08 -0700 Subject: use the body proxy to freeze headers avoid freezing the headers until the web server has actually read data from the body proxy. Once the webserver has read data, then we should throw an error if someone tries to set a header --- actionpack/test/dispatch/live_response_test.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'actionpack/test/dispatch') diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb index 336fdd569b..512f3a8a7a 100644 --- a/actionpack/test/dispatch/live_response_test.rb +++ b/actionpack/test/dispatch/live_response_test.rb @@ -35,6 +35,7 @@ module ActionController @response.stream.close } + @response.await_commit @response.each do |part| assert_equal 'foo', part latch.release @@ -59,21 +60,30 @@ module ActionController assert_nil @response.headers['Content-Length'] end - def test_headers_cannot_be_written_after_write + def test_headers_cannot_be_written_after_webserver_reads @response.stream.write 'omg' + latch = ActiveSupport::Concurrency::Latch.new + t = Thread.new { + @response.stream.each do |chunk| + latch.release + end + } + + latch.await assert @response.headers.frozen? e = assert_raises(ActionDispatch::IllegalStateError) do @response.headers['Content-Length'] = "zomg" end assert_equal 'header already sent', e.message + @response.stream.close + t.join end def test_headers_cannot_be_written_after_close @response.stream.close - assert @response.headers.frozen? e = assert_raises(ActionDispatch::IllegalStateError) do @response.headers['Content-Length'] = "zomg" end -- cgit v1.2.3