parse_formatted_request_parameters does not respect parameters[:format]

I have been working on a project where I need to parse various flavors of XML that are POSTed from various SMS message aggregators into request_parameters. I tried to take advantage of the built in ActionController::Base.param_parsers but ran into some serious problems.

Since I can't control the aggregators' HTTP Content-Type headers to resolve the Mime::Type, I need to rely on the ':format' idiom in Rails routes. So instead of an HTTP POST to '/sms_messages.xml' I POST to '/ sms_messages.clickatell'. Unfortunately the format parameter isn't parsed out of the request until after the param_parser is selected:

http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/request.rb#L414

It appears that the content_type variable can only resolved from the Content-Type header at this point and not from params[:format] (or any other parameters for this matter). I need rails to respect the format of the request over the Content-Type header on a POST or PUT.

I want to fix this but I'm not sure where to start (I get stuck in the recognize_path code... go figure). Any suggestions or help would be greatly appreciated to get me heading down the right path.

Ok I ran into a chicken or egg problem -- I need to have some input from the core team about the intentions of parsing the _method parameter.

When I create a POST or PUT request, RouteSet needs to determine the method (POST, PUT, GET...) of the request. Since browsers only support POST or GET, rails depends on a _method parameter to determine the request method for some requests. When Request#request_method is called, it calls Request#parameters which calls Request#parse_formatted_request_parameters method to try to find the _method parameter (be it in XML, JSON, or whatever). At this point in the request cycle, Request#path_parameters have not yet been determined so I have no way to figure out the parsing strategy based on Request#path_parameters[:format] in Request#parse_formatted_request_parameters. This, coupled with the memoization of Request#parameters, is causing this chicken/egg format problem. Ideally I would run Request#parse_formatted_request_parameters _after_ RouteSet determines the format of the request.

My question is -- do all formats need to be parsed to support the _method parameter? It seems that _method was created to make up for the short comings of web browsers; which implies _method only needs to be parsed for the :url_encoded_form, and :multipart_form formats. When would somebody use the _method parameter in JSON, XML, or some other data format?

Brad

I have been working on a project where I need to parse various flavors of XML that are POSTed from various SMS message aggregators into request_parameters. I tried to take advantage of the built in ActionController::Base.param_parsers but ran into some serious problems.

Since I can't control the aggregators' HTTP Content-Type headers to resolve the Mime::Type, I need to rely on the ':format' idiom in Rails routes. So instead of an HTTP POST to '/sms_messages.xml' I POST to '/ sms_messages.clickatell'. Unfortunately the format parameter isn't parsed out of the request until after the param_parser is selected:

http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/request.rb#L414

It appears that the content_type variable can only resolved from the Content-Type header at this point and not from params[:format] (or any other parameters for this matter). I need rails to respect the format of the request over the Content-Type header on a POST or PUT.

I want to fix this but I'm not sure where to start (I get stuck in the recognize_path code... go figure). Any suggestions or help would be greatly appreciated to get me heading down the right path.

We can't really make the parameter parser depend on params[:format] because we can't figure it out until after we've parsed the parameters already. We could make an exception for the case where the route overrides params[:format] but that doesn't seem particularly tidy.

More fundamentally though, the format in params[:format] is the *response* format, and the parsers are the request format. Seems a mistake to couple those two together.