aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorMichael Koziarski <michael@koziarski.com>2008-06-27 11:29:04 +0300
committerMichael Koziarski <michael@koziarski.com>2008-07-07 07:31:49 +0200
commit2f4aaed7b3feb3be787a316fab3144c06bb21a27 (patch)
tree77604663cd08612a2bbacf1901662ce7ececcf69 /actionpack
parentafa0c7f728a8896c9ee9d932033e08a4c99dfd50 (diff)
downloadrails-2f4aaed7b3feb3be787a316fab3144c06bb21a27.tar.gz
rails-2f4aaed7b3feb3be787a316fab3144c06bb21a27.tar.bz2
rails-2f4aaed7b3feb3be787a316fab3144c06bb21a27.zip
Disable the Accept header by default
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 A special case remains for ajax requests which will have a javascript format for the base resource (/people/1) if the X-Requested-With header is present. This lets ajax pages still use format.js despite there being no params[:format]
Diffstat (limited to 'actionpack')
-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