aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG10
-rwxr-xr-xactionpack/lib/action_controller/base.rb10
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb5
-rw-r--r--actionpack/lib/action_controller/mime_responds.rb6
-rwxr-xr-xactionpack/lib/action_controller/request.rb34
-rw-r--r--actionpack/lib/action_view/base.rb10
-rw-r--r--actionpack/test/controller/caching_test.rb10
-rw-r--r--actionpack/test/controller/content_type_test.rb14
-rw-r--r--actionpack/test/controller/mime_responds_test.rb5
-rw-r--r--actionpack/test/controller/request_test.rb2
10 files changed, 76 insertions, 30 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 7d2ed7538d..f86a3b21fb 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,15 @@
*Edge*
+* Disable the Accept header by default [Michael Koziarski]
+
+ The accept header is poorly implemented by browsers and causes strange
+ errors when used on public sites where crawlers make requests too. You
+ should use formatted urls (e.g. /people/1.xml) to support API clients.
+
+ Alternatively to re-enable it you need to set:
+
+ config.action_controller.use_accept_header = true
+
* Do not stat template files in production mode before rendering. You will no longer be able to modify templates in production mode without restarting the server [Josh Peek]
* Deprecated TemplateHandler line offset [Josh Peek]
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 58eb5cabcd..c28e9005cf 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -340,6 +340,16 @@ module ActionController #:nodoc:
cattr_accessor :optimise_named_routes
self.optimise_named_routes = true
+ # Indicates whether the response format should be determined by examining the Accept HTTP header,
+ # or by using the simpler params + ajax rules.
+ #
+ # If this is set to +true+ then +respond_to+ and +Request#format+ will take the Accept header into
+ # account. If it is set to false (the default) then the request format will be determined solely
+ # by examining params[:format]. If params format is missing, the format will be either HTML or
+ # Javascript depending on whether the request is an AJAX request.
+ cattr_accessor :use_accept_header
+ self.use_accept_header = false
+
# Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
class_inheritable_accessor :allow_forgery_protection
self.allow_forgery_protection = true
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index 234ef8ae5b..f3535f8330 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -166,10 +166,7 @@ module ActionController #:nodoc:
# If there's no extension in the path, check request.format
if extension.nil?
- extension = request.format.to_sym.to_s
- if extension=='all'
- extension = nil
- end
+ extension = request.cache_format
end
extension
end
diff --git a/actionpack/lib/action_controller/mime_responds.rb b/actionpack/lib/action_controller/mime_responds.rb
index 1dbd8b9e6f..29294476f7 100644
--- a/actionpack/lib/action_controller/mime_responds.rb
+++ b/actionpack/lib/action_controller/mime_responds.rb
@@ -114,7 +114,11 @@ module ActionController #:nodoc:
@request = controller.request
@response = controller.response
- @mime_type_priority = Array(Mime::Type.lookup_by_extension(@request.parameters[:format]) || @request.accepts)
+ if ActionController::Base.use_accept_header
+ @mime_type_priority = Array(Mime::Type.lookup_by_extension(@request.parameters[:format]) || @request.accepts)
+ else
+ @mime_type_priority = [@request.format]
+ end
@order = []
@responses = {}
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index c91a3387a0..c76a93f7a1 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -89,14 +89,23 @@ module ActionController
end
end
- # Returns the Mime type for the format used in the request. If there is no format available, the first of the
- # accept types will be used. Examples:
+ # Returns the Mime type for the format used in the request.
#
# GET /posts/5.xml | request.format => Mime::XML
# GET /posts/5.xhtml | request.format => Mime::HTML
- # GET /posts/5 | request.format => request.accepts.first (usually Mime::HTML for browsers)
+ # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>
def format
- @format ||= parameters[:format] ? Mime::Type.lookup_by_extension(parameters[:format]) : accepts.first
+ @format ||= begin
+ if parameters[:format]
+ Mime::Type.lookup_by_extension(parameters[:format])
+ elsif ActionController::Base.use_accept_header
+ accepts.first
+ elsif xhr?
+ Mime::Type.lookup_by_extension("js")
+ else
+ Mime::Type.lookup_by_extension("html")
+ end
+ end
end
@@ -116,19 +125,26 @@ module ActionController
@format = Mime::Type.lookup_by_extension(parameters[:format])
end
+ # Returns a symbolized version of the <tt>:format</tt> parameter of the request.
+ # If no format is given it returns <tt>:js</tt>for AJAX requests and <tt>:html</tt>
+ # otherwise.
def template_format
parameter_format = parameters[:format]
- case
- when parameter_format.blank? && !xhr?
- :html
- when parameter_format.blank? && xhr?
+ if parameter_format
+ parameter_format.to_sym
+ elsif xhr?
:js
else
- parameter_format.to_sym
+ :html
end
end
+ def cache_format
+ parameter_format = parameters[:format]
+ parameter_format && parameter_format.to_sym
+ end
+
# Returns true if the request's "X-Requested-With" header contains
# "XMLHttpRequest". (The Prototype Javascript library sends this header with
# every Ajax request.)
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 92501133a6..66892fdabf 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -256,13 +256,9 @@ module ActionView #:nodoc:
template_path.split('/').last[0,1] != '_'
end
- # Returns a symbolized version of the <tt>:format</tt> parameter of the request,
- # or <tt>:html</tt> by default.
- #
- # EXCEPTION: If the <tt>:format</tt> parameter is not set, the Accept header will be examined for
- # whether it contains the JavaScript mime type as its first priority. If that's the case,
- # it will be used. This ensures that Ajax applications can use the same URL to support both
- # JavaScript and non-JavaScript users.
+ # The format to be used when choosing between multiple templates with
+ # the same name but differing formats. See +Request#template_format+
+ # for more details.
def template_format
return @template_format if @template_format
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index d8a3ccb35b..7aa4e0cd93 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -131,8 +131,7 @@ class PageCachingTest < Test::Unit::TestCase
end
def test_page_caching_conditional_options
- @request.env['HTTP_ACCEPT'] = 'application/json'
- get :ok
+ get :ok, :format=>'json'
assert_page_not_cached :ok
end
@@ -219,6 +218,7 @@ class ActionCachingMockController
Object.new.instance_eval(<<-EVAL)
def path; '#{@mock_path}' end
def format; 'all' end
+ def cache_format; nil end
self
EVAL
end
@@ -414,12 +414,6 @@ class ActionCacheTest < Test::Unit::TestCase
assert_equal 'application/xml', @response.content_type
reset!
- @request.env['HTTP_ACCEPT'] = "application/xml"
- get :index
- assert_equal cached_time, @response.body
- assert_equal 'application/xml', @response.content_type
- reset!
-
get :expire_xml
reset!
diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb
index 2019b4a2d0..8f55974172 100644
--- a/actionpack/test/controller/content_type_test.rb
+++ b/actionpack/test/controller/content_type_test.rb
@@ -114,6 +114,20 @@ class ContentTypeTest < Test::Unit::TestCase
assert_equal Mime::HTML, @response.content_type
assert_equal "utf-8", @response.charset
end
+end
+
+class AcceptBasedContentTypeTest < ActionController::TestCase
+
+ tests ContentTypeController
+
+ def setup
+ ActionController::Base.use_accept_header = true
+ end
+
+ def tear_down
+ ActionController::Base.use_accept_header = false
+ end
+
def test_render_default_content_types_for_respond_to
@request.env["HTTP_ACCEPT"] = Mime::HTML.to_s
diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb
index fb2519563d..17f5e27232 100644
--- a/actionpack/test/controller/mime_responds_test.rb
+++ b/actionpack/test/controller/mime_responds_test.rb
@@ -166,6 +166,7 @@ RespondToController.view_paths = [FIXTURE_LOAD_PATH]
class MimeControllerTest < Test::Unit::TestCase
def setup
+ ActionController::Base.use_accept_header = true
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@@ -173,6 +174,10 @@ class MimeControllerTest < Test::Unit::TestCase
@request.host = "www.example.com"
end
+ def teardown
+ ActionController::Base.use_accept_header = false
+ end
+
def test_html
@request.env["HTTP_ACCEPT"] = "text/html"
get :js_or_html
diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb
index 20f3fd4d7b..932c0e21a1 100644
--- a/actionpack/test/controller/request_test.rb
+++ b/actionpack/test/controller/request_test.rb
@@ -386,7 +386,7 @@ class RequestTest < Test::Unit::TestCase
def test_nil_format
@request.instance_eval { @parameters = { :format => nil } }
- @request.env["HTTP_ACCEPT"] = "text/javascript"
+ @request.env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
assert_equal Mime::JS, @request.format
end