I have a controller method in Ruby on Rails 3 that accepts application/JSON as the content type. This all works as expected, but I actually do not want rails to automatically parse the JSON in the body of the POST request. This method is acting as a gateway and just shuttles the information in to a queue and could be quite large. I do not want to waste the time processing the data in to the @_params since it's unnecessary.
I believe I could get around this by setting the content-type in the header of the request to something else, but I would like to be semantically correct for the HTTP requests.
How can I disable this functionality?
EDIT: more specifically how can I edit this functionality for just this one route?
Parameter parsing is baked pretty deeply inside actionpack's lib/action_dispatch/middleware/params_parser.rb
.
I'd say the best you're going to get away with is intercepting the request with Rack, something like this.
In lib/raw_json.rb
module Rack
class RawJSON
def initialize(app)
@app = app
end
def call(env)
request = Request.new(env)
if request.content_type =~ /application\/json/i
# test request.path here to limit your processing to particular actions
raw_json = env['rack.input'].read
env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
env['rack.input'] = StringIO.new("raw_json=#{raw_json}")
end
return @app.call(env)
end
end
end
In config.ru
, insert this before the call to run <your app name>::Application
require 'raw_json'
use Rack::RawJSON
The overhead for parsing the JSON from a single request is relatively low. Do you have a specific reason to believe that processing the JSON is contributing to any kind of slowness in overall processing?
If not, then I'd recommend that you leave this as it is until such time is it can be identified as a problem.
Configuring rails to not parse that JSON (either via some sort of rack configuration or in some other method) will create at lest one route in your application that is not handled in a standard Rails Way.
Eventually, you may find yourself having to do some sort of processing of this data. Or maybe you'll need to put some sort of security in front of it. Or maybe you'll want to log it and related it to the user that sent it. And when that day comes you (or someone else on your team) will need to go in and make changes to this non-standard implementation.
Doing things in a non-standard way in a Rails implementation can add to the complexity and time to maintain the software. It is also a common source of defects since people are less familiar with non-standard processing.
So unless it is a real issue, I'd recommend just letting rails process the JSON and then simply pass it through the normal Rails Way.
It may be baked in, but looking at the code:
module ActionDispatch
class ParamsParser
DEFAULT_PARSERS = {
Mime::XML => :xml_simple,
Mime::JSON => :json
}
def initialize(app, parsers = {})
@app, @parsers = app, DEFAULT_PARSERS.merge(parsers)
end
[ ... ]
strategy = @parsers[mime_type]
So, if you can arrange to send a hash to this initializer, you can add or override the default. Not sure the allow for removing, but an empty parser method could work.
Parsers answer here: How do I initialize ActionDispatch::ParamsParser in Rails 3.1?
Code is from actionpack-3.2.8/lib/action_dispatch/middleware/params_parser.rb
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With