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

Changeset 3777

Show
Ignore:
Timestamp:
03/05/06 18:59:58 (3 years ago)
Author:
xal
Message:

Added new infrastructure support for REST webservices.

By default application/xml posts are handled by creating a XmlNode object with the same name as the root element of the submitted xml. M$

ActionController::Base.param_parsersapplication/atom+xml? = Proc.new do |data|

node = REXML::Document.new(post)

{ node.root.name => node.root }

end

XmlSimple and Yaml web services were retired, ActionController::Base.param_parsers carries an example which shows how to get this functio$
request.[formatted_post?, xml_post?, yaml_post? and post_format] were all deprecated in favor of request.content_type [Tobias Luetke]

Closes #4081

Files:

Legend:

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

    r3767 r3777  
    11*SVN* 
    22 
     3* Added new infrastructure support for REST webservices.  
     4  By default application/xml posts are handled by creating a XmlNode object with the same name as the root element of the submitted xml. More handlers can easily be registered like this 
     5 
     6 ActionController::Base.param_parsers['application/atom+xml'] = Proc.new do |data|  
     7    node = REXML::Document.new(post)  
     8   { node.root.name => node.root } 
     9 end 
     10  
     11 XmlSimple and Yaml web services were retired, ActionController::Base.param_parsers carries an example which shows how to get this functionality back.  
     12 request.[formatted_post?, xml_post?, yaml_post? and post_format] were all deprecated in favor of request.content_type [Tobias Luetke] 
     13  
    314* Fixed Effect.Appear in effects.js to work with floats in Safari #3524, #3813, #3044 [Thomas Fuchs] 
    415 
  • trunk/actionpack/lib/action_controller.rb

    r3580 r3777  
    3737require 'action_controller/base' 
    3838require 'action_controller/deprecated_redirects' 
     39require 'action_controller/request' 
     40require 'action_controller/deprecated_request_methods' 
    3941require 'action_controller/rescue' 
    4042require 'action_controller/benchmarking' 
  • trunk/actionpack/lib/action_controller/base.rb

    r3668 r3777  
    261261    cattr_accessor :allow_concurrency 
    262262 
     263    # Modern REST web services often need to submit complex data to the web application.  
     264    # the param_parsers hash lets you register handlers wich will process the http body and add parameters to the  
     265    # @params hash. These handlers are invoked for post and put requests. 
     266    # 
     267    # By default application/xml is enabled. a XmlNode class with the same param name as the root  
     268    # will be instanciated in the @params.  
     269    #  
     270    # Example: 
     271    # 
     272    #   ActionController::Base.param_parsers['application/atom+xml'] = Proc.new do |data|  
     273    #      node = REXML::Document.new(post)  
     274    #     { node.root.name => node.root } 
     275    #   end 
     276    # 
     277    # Note: Up until release 1.1 rails would default to using XmlSimple for such requests. To get the old  
     278    # behavior you can re-register XmlSimple as application/xml handler and enable application/x-yaml like  
     279    # this: 
     280    # 
     281    #   ActionController::Base.param_parsers['application/xml'] = Proc.new do |data|  
     282    #     XmlSimple.xml_in(data, 'ForceArray' => false) 
     283    #   end 
     284    # 
     285    #   ActionController::Base.param_parsers['application/x-yaml'] = Proc.new do |data|  
     286    #     |post| YAML.load(post) 
     287    #   end 
     288    # 
     289    @@param_parsers = { 
     290      'application/xml'     => Proc.new { |post| node = XmlNode.from_xml(post); { node.node_name => node } }, 
     291    } 
     292    cattr_accessor :param_parsers  
     293 
    263294    # Template root determines the base from which template references will be made. So a call to render("test/template") 
    264295    # will be converted to "#{template_root}/test/template.rhtml". 
    265296    class_inheritable_accessor :template_root 
    266  
     297     
    267298    # The logger is used for generating information on the action run-time (including benchmarking) if available. 
    268299    # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. 
     
    303334    # Returns the name of the action this controller is processing. 
    304335    attr_accessor :action_name 
    305  
     336     
    306337    class << self 
    307338      # Factory for the standard create, process loop where the controller is discarded after processing. 
  • trunk/actionpack/lib/action_controller/cgi_ext/cgi_methods.rb

    r2379 r3777  
    11require 'cgi' 
    22require 'action_controller/vendor/xml_simple' 
     3require 'action_controller/vendor/xml_node' 
    34 
    45# Static methods for parsing the query and request parameters that can be used in 
     
    5960 
    6061    def self.parse_formatted_request_parameters(format, raw_post_data) 
    61       case format 
    62         when :xml 
    63           return XmlSimple.xml_in(raw_post_data, 'ForceArray' => false) 
    64         when :yaml 
    65           return YAML.load(raw_post_data) 
    66       end 
     62      ActionController::Base.param_parsers[format].call(raw_post_data) || {} 
    6763    rescue Object => e 
    6864      { "exception" => "#{e.message} (#{e.class})", "backtrace" => e.backtrace,  
  • trunk/actionpack/lib/action_controller/cgi_process.rb

    r3768 r3777  
    6565 
    6666    def request_parameters 
    67       if formatted_post? 
    68         CGIMethods.parse_formatted_request_parameters(post_format, @env['RAW_POST_DATA']) 
     67      if ActionController::Base.param_parsers.has_key?(content_type) 
     68        CGIMethods.parse_formatted_request_parameters(content_type, @env['RAW_POST_DATA']) 
    6969      else 
    7070        CGIMethods.parse_request_parameters(@cgi.params) 
  • trunk/actionpack/lib/action_controller/request.rb

    r3563 r3777  
    4343    end 
    4444 
    45     # Determine whether the body of a POST request is URL-encoded (default), 
    46     # XML, or YAML by checking the Content-Type HTTP header: 
    47     # 
    48     #   Content-Type        Post Format 
    49     #   application/xml     :xml 
    50     #   text/xml            :xml 
    51     #   application/x-yaml  :yaml 
    52     #   text/x-yaml         :yaml 
    53     #   *                   :url_encoded 
     45    # Determine whether the body of a HTTP call is URL-encoded (default) 
     46    # or matches one of the registered param_parsers.  
    5447    # 
    5548    # For backward compatibility, the post format is extracted from the 
    5649    # X-Post-Data-Format HTTP header if present. 
    57     def post_format 
    58       @post_format ||= 
    59            if @env['HTTP_X_POST_DATA_FORMAT'] 
    60              @env['HTTP_X_POST_DATA_FORMAT'].downcase.to_sym 
    61            else 
    62              case @env['CONTENT_TYPE'].to_s.downcase 
    63              when 'application/xml', 'text/xml'        then :xml 
    64              when 'application/x-yaml', 'text/x-yaml'  then :yaml 
    65              else :url_encoded 
    66              end 
    67            end 
    68     end 
    69  
    70     # Is this a POST request formatted as XML or YAML? 
    71     def formatted_post? 
    72       post? && (post_format == :xml || post_format == :yaml) 
    73     end 
    74  
    75     # Is this a POST request formatted as XML? 
    76     def xml_post? 
    77       post? && post_format == :xml 
    78     end 
    79  
    80     # Is this a POST request formatted as YAML? 
    81     def yaml_post? 
    82       post? && post_format == :yaml 
     50    def content_type 
     51      return @content_type if @content_type 
     52 
     53      @content_type = @env['CONTENT_TYPE'].to_s.downcase 
     54       
     55      if @env['HTTP_X_POST_DATA_FORMAT']           
     56        case @env['HTTP_X_POST_DATA_FORMAT'].downcase.to_sym 
     57        when :yaml 
     58          @content_type = 'application/x-yaml' 
     59        when :xml 
     60          @content_type = 'application/xml' 
     61        end 
     62      end 
     63      @content_type 
    8364    end 
    8465 
  • trunk/actionpack/test/abstract_unit.rb

    r3003 r3777  
    33$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') 
    44 
     5require 'yaml' 
    56require 'test/unit' 
    67require 'action_controller' 
     
    1213ActionController::Base.ignore_missing_templates = false 
    1314ActionController::Routing::Routes.reload rescue nil 
    14