public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
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]
NZKoz (author)
Fri Jun 27 01:29:04 -0700 2008
commit  2f4aaed7b3feb3be787a316fab3144c06bb21a27
tree    77604663cd08612a2bbacf1901662ce7ececcf69
parent  afa0c7f728a8896c9ee9d932033e08a4c99dfd50
...
1
2
 
 
 
 
 
 
 
 
 
 
3
4
5
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
@@ -1,5 +1,15 @@
0
 *Edge*
0
 
0
+* Disable the Accept header by default [Michael Koziarski]
0
+
0
+    The accept header is poorly implemented by browsers and causes strange
0
+  errors when used on public sites where crawlers make requests too.  You
0
+  should use formatted urls (e.g. /people/1.xml) to support API clients.
0
+
0
+  Alternatively to re-enable it you need to set:
0
+
0
+  config.action_controller.use_accept_header = true
0
+
0
 * 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]
0
 
0
 * Deprecated TemplateHandler line offset [Josh Peek]
...
340
341
342
 
 
 
 
 
 
 
 
 
 
343
344
345
...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
0
@@ -340,6 +340,16 @@ module ActionController #:nodoc:
0
     cattr_accessor :optimise_named_routes
0
     self.optimise_named_routes = true
0
 
0
+    # Indicates whether the response format should be determined by examining the Accept HTTP header,
0
+    # or by using the simpler params + ajax rules.
0
+    #
0
+    # If this is set to +true+ then +respond_to+ and +Request#format+ will take the Accept header into
0
+    # account.  If it is set to false (the default) then the request format will be determined solely
0
+    # by examining params[:format].  If params format is missing, the format will be either HTML or
0
+    # Javascript depending on whether the request is an AJAX request.
0
+    cattr_accessor :use_accept_header
0
+    self.use_accept_header = false
0
+
0
     # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
0
     class_inheritable_accessor :allow_forgery_protection
0
     self.allow_forgery_protection = true
...
166
167
168
169
170
171
172
 
173
174
175
...
166
167
168
 
 
 
 
169
170
171
172
0
@@ -166,10 +166,7 @@ module ActionController #:nodoc:
0
 
0
             # If there's no extension in the path, check request.format
0
             if extension.nil?
0
-              extension = request.format.to_sym.to_s
0
-              if extension=='all'
0
-                extension = nil
0
-              end
0
+              extension = request.cache_format
0
             end
0
             extension
0
           end
...
114
115
116
117
 
 
 
 
 
118
119
120
...
114
115
116
 
117
118
119
120
121
122
123
124
0
@@ -114,7 +114,11 @@ module ActionController #:nodoc:
0
         @request    = controller.request
0
         @response   = controller.response
0
 
0
-        @mime_type_priority = Array(Mime::Type.lookup_by_extension(@request.parameters[:format]) || @request.accepts)
0
+        if ActionController::Base.use_accept_header
0
+          @mime_type_priority = Array(Mime::Type.lookup_by_extension(@request.parameters[:format]) || @request.accepts)
0
+        else
0
+          @mime_type_priority = [@request.format]
0
+        end
0
 
0
         @order     = []
0
         @responses = {}
...
89
90
91
92
93
 
94
95
96
97
 
98
99
 
 
 
 
 
 
 
 
 
 
 
100
101
102
...
116
117
118
 
 
 
119
120
121
122
123
124
125
 
 
 
126
127
128
 
129
130
131
 
 
 
 
 
132
133
134
...
89
90
91
 
 
92
93
94
95
 
96
97
 
98
99
100
101
102
103
104
105
106
107
108
109
110
111
...
125
126
127
128
129
130
131
132
133
 
 
 
 
134
135
136
137
138
 
139
140
141
142
143
144
145
146
147
148
149
150
0
@@ -89,14 +89,23 @@ module ActionController
0
         end
0
     end
0
 
0
-    # Returns the Mime type for the format used in the request. If there is no format available, the first of the 
0
-    # accept types will be used. Examples:
0
+    # Returns the Mime type for the format used in the request.
0
     #
0
     #   GET /posts/5.xml   | request.format => Mime::XML
0
     #   GET /posts/5.xhtml | request.format => Mime::HTML
0
-    #   GET /posts/5       | request.format => request.accepts.first (usually Mime::HTML for browsers)
0
+    #   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>
0
     def format
0
-      @format ||= parameters[:format] ? Mime::Type.lookup_by_extension(parameters[:format]) : accepts.first
0
+      @format ||= begin
0
+        if parameters[:format]
0
+          Mime::Type.lookup_by_extension(parameters[:format])
0
+        elsif ActionController::Base.use_accept_header
0
+          accepts.first
0
+        elsif xhr?
0
+          Mime::Type.lookup_by_extension("js")
0
+        else
0
+          Mime::Type.lookup_by_extension("html")
0
+        end
0
+      end
0
     end
0
     
0
     
0
@@ -116,19 +125,26 @@ module ActionController
0
       @format = Mime::Type.lookup_by_extension(parameters[:format])
0
     end
0
 
0
+    # Returns a symbolized version of the <tt>:format</tt> parameter of the request.
0
+    # If no format is given it returns <tt>:js</tt>for AJAX requests and <tt>:html</tt>
0
+    # otherwise.
0
     def template_format
0
       parameter_format = parameters[:format]
0
 
0
-      case
0
-      when parameter_format.blank? && !xhr?
0
-        :html
0
-      when parameter_format.blank? && xhr?
0
+      if parameter_format
0
+        parameter_format.to_sym
0
+      elsif xhr?
0
         :js
0
       else
0
-        parameter_format.to_sym
0
+        :html
0
       end
0
     end
0
 
0
+    def cache_format
0
+      parameter_format = parameters[:format]
0
+      parameter_format && parameter_format.to_sym
0
+    end
0
+
0
     # Returns true if the request's "X-Requested-With" header contains
0
     # "XMLHttpRequest". (The Prototype Javascript library sends this header with
0
     # every Ajax request.)
...
256
257
258
259
260
261
262
263
264
265
 
 
 
266
267
268
...
256
257
258
 
 
 
 
 
 
 
259
260
261
262
263
264
0
@@ -256,13 +256,9 @@ module ActionView #:nodoc:
0
       template_path.split('/').last[0,1] != '_'
0
     end
0
 
0
-    # Returns a symbolized version of the <tt>:format</tt> parameter of the request,
0
-    # or <tt>:html</tt> by default.
0
-    #
0
-    # EXCEPTION: If the <tt>:format</tt> parameter is not set, the Accept header will be examined for
0
-    # whether it contains the JavaScript mime type as its first priority. If that's the case,
0
-    # it will be used. This ensures that Ajax applications can use the same URL to support both
0
-    # JavaScript and non-JavaScript users.
0
+    # The format to be used when choosing between multiple templates with
0
+    # the same name but differing formats.  See +Request#template_format+
0
+    # for more details.
0
     def template_format
0
       return @template_format if @template_format
0
 
...
131
132
133
134
135
 
136
137
138
...
219
220
221
 
222
223
224
...
414
415
416
417
418
419
420
421
422
423
424
425
...
131
132
133
 
 
134
135
136
137
...
218
219
220
221
222
223
224
...
414
415
416
 
 
 
 
 
 
417
418
419
0
@@ -131,8 +131,7 @@ class PageCachingTest < Test::Unit::TestCase
0
   end
0
 
0
   def test_page_caching_conditional_options
0
-    @request.env['HTTP_ACCEPT'] = 'application/json'
0
-    get :ok
0
+    get :ok, :format=>'json'
0
     assert_page_not_cached :ok
0
   end
0
 
0
@@ -219,6 +218,7 @@ class ActionCachingMockController
0
     Object.new.instance_eval(<<-EVAL)
0
       def path; '#{@mock_path}' end
0
       def format; 'all' end
0
+      def cache_format; nil end
0
       self
0
     EVAL
0
   end
0
@@ -414,12 +414,6 @@ class ActionCacheTest < Test::Unit::TestCase
0
       assert_equal 'application/xml', @response.content_type
0
       reset!
0
 
0
-      @request.env['HTTP_ACCEPT'] = "application/xml"
0
-      get :index
0
-      assert_equal cached_time, @response.body
0
-      assert_equal 'application/xml', @response.content_type
0
-      reset!
0
-
0
       get :expire_xml
0
       reset!
0
 
...
114
115
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
118
119
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
0
@@ -114,6 +114,20 @@ class ContentTypeTest < Test::Unit::TestCase
0
     assert_equal Mime::HTML, @response.content_type
0
     assert_equal "utf-8", @response.charset
0
   end
0
+end
0
+
0
+class AcceptBasedContentTypeTest < ActionController::TestCase
0
+
0
+  tests ContentTypeController
0
+
0
+  def setup
0
+    ActionController::Base.use_accept_header = true
0
+  end
0
+
0
+  def tear_down
0
+    ActionController::Base.use_accept_header = false
0
+  end
0
+
0
 
0
   def test_render_default_content_types_for_respond_to
0
     @request.env["HTTP_ACCEPT"] = Mime::HTML.to_s
...
166
167
168
 
169
170
171
...
173
174
175
 
 
 
 
176
177
178
...
166
167
168
169
170
171
172
...
174
175
176
177
178
179
180
181
182
183
0
@@ -166,6 +166,7 @@ RespondToController.view_paths = [FIXTURE_LOAD_PATH]
0
 
0
 class MimeControllerTest < Test::Unit::TestCase
0
   def setup
0
+    ActionController::Base.use_accept_header = true
0
     @request    = ActionController::TestRequest.new
0
     @response   = ActionController::TestResponse.new
0
 
0
@@ -173,6 +174,10 @@ class MimeControllerTest < Test::Unit::TestCase
0
     @request.host = "www.example.com"
0
   end
0
 
0
+  def teardown
0
+    ActionController::Base.use_accept_header = false
0
+  end
0
+
0
   def test_html
0
     @request.env["HTTP_ACCEPT"] = "text/html"
0
     get :js_or_html
...
386
387
388
389
 
390
391
392
...
386
387
388
 
389
390
391
392
0
@@ -386,7 +386,7 @@ class RequestTest < Test::Unit::TestCase
0
 
0
   def test_nil_format
0
     @request.instance_eval { @parameters = { :format => nil } }
0
-    @request.env["HTTP_ACCEPT"] = "text/javascript"
0
+    @request.env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
0
     assert_equal Mime::JS, @request.format
0
   end
0
 

Comments