Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 3917

Show
Ignore:
Timestamp:
03/18/06 06:15:28 (2 years ago)
Author:
minam
Message:

Make Mime::Type.parse consider q values (if any)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r3915 r3917  
    11*SVN* 
     2 
     3* Make Mime::Type.parse consider q values (if any) [Jamis Buck] 
    24 
    35* XML-formatted requests are typecast according to "type" attributes for :xml_simple [Jamis Buck] 
  • trunk/actionpack/lib/action_controller/mime_type.rb

    r3873 r3917  
    11module Mime 
    22  class Type 
     3 
     4    # A simple helper class used in parsing the accept header 
     5    class AcceptItem #:nodoc: 
     6      attr_accessor :order, :name, :q 
     7 
     8      def initialize(order, name, q=nil) 
     9        @order = order 
     10        @name = name.strip 
     11        q ||= 0.0 if @name == "*/*" # default "*/*" to end of list 
     12        @q = ((q || 1.0).to_f * 100).to_i 
     13      end 
     14 
     15      def to_s 
     16        @name 
     17      end 
     18 
     19      def <=>(item) 
     20        result = item.q <=> q 
     21        result = order <=> item.order if result == 0 
     22        result 
     23      end 
     24 
     25      def ==(item) 
     26        name == (item.respond_to?(:name) ? item.name : item) 
     27      end 
     28    end 
     29 
    330    class << self 
    431      def lookup(string) 
     
    734 
    835      def parse(accept_header) 
    9         mime_types = accept_header.split(",").collect! do |mime_type| 
    10           mime_type.split(";").first.strip 
     36        # keep track of creation order to keep the subsequent sort stable 
     37        index = 0 
     38        list = accept_header.split(/,/). 
     39          map! { |i| AcceptItem.new(index += 1, *i.split(/;\s*q=/)) }.sort! 
     40 
     41        # Take care of the broken text/xml entry by renaming or deleting it 
     42   
     43        text_xml = list.index("text/xml") 
     44        app_xml = list.index("application/xml") 
     45 
     46        if text_xml && app_xml 
     47          # set the q value to the max of the two 
     48          list[app_xml].q = [list[text_xml].q, list[app_xml].q].max 
     49 
     50          # make sure app_xml is ahead of text_xml in the list 
     51          if app_xml > text_xml 
     52            list[app_xml], list[text_xml] = list[text_xml], list[app_xml] 
     53            app_xml, text_xml = text_xml, app_xml 
     54          end 
     55 
     56          # delete text_xml from the list 
     57          list.delete_at(text_xml) 
     58   
     59        elsif text_xml 
     60          list[text_xml].name = "application/xml" 
    1161        end 
    1262 
    13         reorder_xml_types!(mime_types) 
    14         mime_types.collect! { |mime_type| Mime::Type.lookup(mime_type) } 
    15       end 
    16        
    17       private 
    18         def reorder_xml_types!(mime_types) 
    19           mime_types.delete("text/xml") if mime_types.include?("application/xml") 
     63        # Look for more specific xml-based types and sort them ahead of app/xml 
    2064 
    21           if index_for_generic_xml = mime_types.index("application/xml") 
    22             specific_xml_types = mime_types[index_for_generic_xml..-1].grep(/application\/[a-z]*\+xml/) 
     65        if app_xml 
     66          idx = app_xml 
     67          app_xml_type = list[app_xml] 
    2368 
    24             for specific_xml_type in specific_xml_types.reverse 
    25               mime_types.insert(index_for_generic_xml, mime_types.delete(specific_xml_type)) 
     69          while(idx < list.length) 
     70            type = list[idx] 
     71            break if type.q < app_xml_type.q 
     72            if type.name =~ /\+xml$/ 
     73              list[app_xml], list[idx] = list[idx], list[app_xml] 
     74              app_xml = idx 
    2675            end 
     76            idx += 1 
    2777          end 
    2878        end 
     79 
     80        list.map! { |i| Mime::Type.lookup(i.name) }.uniq! 
     81        list 
     82      end 
    2983    end 
    3084