aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
authorJamis Buck <jamis@37signals.com>2006-03-18 06:15:28 +0000
committerJamis Buck <jamis@37signals.com>2006-03-18 06:15:28 +0000
commit4e0028fbaba3b0497ba5a0fbf0cd314137b7aa8f (patch)
tree44bc56bae1b5b4321dffe27eb9987eca48b68874 /actionpack/lib
parent263479b5a344e5882f4941e3f18faf9f027b0615 (diff)
downloadrails-4e0028fbaba3b0497ba5a0fbf0cd314137b7aa8f.tar.gz
rails-4e0028fbaba3b0497ba5a0fbf0cd314137b7aa8f.tar.bz2
rails-4e0028fbaba3b0497ba5a0fbf0cd314137b7aa8f.zip
Make Mime::Type.parse consider q values (if any)
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3917 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_controller/mime_type.rb80
1 files changed, 67 insertions, 13 deletions
diff --git a/actionpack/lib/action_controller/mime_type.rb b/actionpack/lib/action_controller/mime_type.rb
index 35095dc770..43c4b056f7 100644
--- a/actionpack/lib/action_controller/mime_type.rb
+++ b/actionpack/lib/action_controller/mime_type.rb
@@ -1,31 +1,85 @@
module Mime
class Type
+
+ # A simple helper class used in parsing the accept header
+ class AcceptItem #:nodoc:
+ attr_accessor :order, :name, :q
+
+ def initialize(order, name, q=nil)
+ @order = order
+ @name = name.strip
+ q ||= 0.0 if @name == "*/*" # default "*/*" to end of list
+ @q = ((q || 1.0).to_f * 100).to_i
+ end
+
+ def to_s
+ @name
+ end
+
+ def <=>(item)
+ result = item.q <=> q
+ result = order <=> item.order if result == 0
+ result
+ end
+
+ def ==(item)
+ name == (item.respond_to?(:name) ? item.name : item)
+ end
+ end
+
class << self
def lookup(string)
LOOKUP[string]
end
def parse(accept_header)
- mime_types = accept_header.split(",").collect! do |mime_type|
- mime_type.split(";").first.strip
+ # keep track of creation order to keep the subsequent sort stable
+ index = 0
+ list = accept_header.split(/,/).
+ map! { |i| AcceptItem.new(index += 1, *i.split(/;\s*q=/)) }.sort!
+
+ # Take care of the broken text/xml entry by renaming or deleting it
+
+ text_xml = list.index("text/xml")
+ app_xml = list.index("application/xml")
+
+ if text_xml && app_xml
+ # set the q value to the max of the two
+ list[app_xml].q = [list[text_xml].q, list[app_xml].q].max
+
+ # make sure app_xml is ahead of text_xml in the list
+ if app_xml > text_xml
+ list[app_xml], list[text_xml] = list[text_xml], list[app_xml]
+ app_xml, text_xml = text_xml, app_xml
+ end
+
+ # delete text_xml from the list
+ list.delete_at(text_xml)
+
+ elsif text_xml
+ list[text_xml].name = "application/xml"
end
- reorder_xml_types!(mime_types)
- mime_types.collect! { |mime_type| Mime::Type.lookup(mime_type) }
- end
-
- private
- def reorder_xml_types!(mime_types)
- mime_types.delete("text/xml") if mime_types.include?("application/xml")
+ # Look for more specific xml-based types and sort them ahead of app/xml
- if index_for_generic_xml = mime_types.index("application/xml")
- specific_xml_types = mime_types[index_for_generic_xml..-1].grep(/application\/[a-z]*\+xml/)
+ if app_xml
+ idx = app_xml
+ app_xml_type = list[app_xml]
- for specific_xml_type in specific_xml_types.reverse
- mime_types.insert(index_for_generic_xml, mime_types.delete(specific_xml_type))
+ while(idx < list.length)
+ type = list[idx]
+ break if type.q < app_xml_type.q
+ if type.name =~ /\+xml$/
+ list[app_xml], list[idx] = list[idx], list[app_xml]
+ app_xml = idx
end
+ idx += 1
end
end
+
+ list.map! { |i| Mime::Type.lookup(i.name) }.uniq!
+ list
+ end
end
def initialize(string, symbol = nil, synonyms = [])