2012-04-18 4 views
17

コンテンツタイプとしてapplication/JSONを受け付けるRuby on Rails 3のコントローラメソッドがあります。これはすべて正常に動作しますが、実際にはPOSTリクエストの本体でJSONを自動的に解析するようにはしません。この方法はゲートウェイとして機能し、情報をキューに入れてシャトルして、非常に大きくなる可能性があります。 @ _paramsにデータを処理する時間を無駄にしたくないので、それは不要です。Rubyでレール3がJSONポストを解析しないようにする

私は何か他のものへのリクエストのヘッダにコンテンツタイプを設定することでこれを回避できたと考えているが、私は、HTTP要求のために意味的に正しいことをしたいと思います。

どうすればこの機能を無効にできますか?

EDIT: より具体的にどのように私はこの1つのだけルートのこの機能を編集することができますか?

+0

からですJSONとして投稿すると、Railsは常に解析すると思います。あなたが描いていることをするためには、私はあなたがそのルートにラックのエンドポイントをマウントし、 'rack_raw_upload'のようなユーティリティを使ってPOSTを処理したいと思うと思います...良い質問、申し訳ありません。 – Andrew

+0

興味深い考え方...私はそのショットを与え、それがどうなるか見ることができます。 – Macdiesel

答えて

13

パラメータ解析は、アクションパックlib/action_dispatch/middleware/params_parser.rbのかなり深く焼き付けられています。

私は、あなたが離れて逃げようとしている最善のことは、このような何かをRackで傍受していると言います。 config.rulib/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 

run <your app name>::Application

require 'raw_json' 
use Rack::RawJSON 
+0

は、このソリューションに追加する必要があるすべてのものが特定のルートを検出するためのものだと思われます。 'if request.path == '/ foo'とrequest.content_type =〜/ application// json/i' –

+0

はい、そのため、request.pathをテストするコードにコメントを付けます。 –

+0

私はまだこれを試していませんが、それは解決策の妥当性のように思えます。 – Macdiesel

1

への呼び出し比較的低い単一の要求からJSONを解析するためのオーバーヘッドの前にこれを挿入します。 JSONの処理が処理全体の遅さに寄与していると考える具体的な理由はありますか?

れていない場合、私はそのような時は、それが問題として識別することが可能になるまで、そのまま使用すると、このままにしておくことをお勧めします。

JSONを何らかの種類のラック構成やその他の方法で解析しないようにレールを設定すると、アプリケーションで標準で処理されないルートが1つ作成されますRails Way

最終的に、このデータを何らかの処理をしなければならないことがあります。あるいは、セキュリティの前に何らかのセキュリティを置く必要があるかもしれません。または、ログに記録し、それを送信したユーザーに関連付けることもできます。そして、その日が来たら(あなたのチームの他の誰かが)、この非標準的な実装に入り、変更を加える必要があります。

Rails実装で非標準的なやり方で行うことは、ソフトウェアの複雑さと時間を増加させる可能性があります。人々は非標準的な処理に慣れていないので、これはまた、一般的な欠陥の原因です。

実際の問題がなければ、レールでJSONを処理してから、通常の方法でを渡すことをおすすめします。Rails Wayそれはで焼きますが、コードを見てすることができる

+1

これは質問に答えません。私は、ほとんどの場合、最適化のために着信json応答を解析しないようにしています。 jsonボディは、数万のアイテムを持つ配列になる可能性があり、これを解析して繰り返し処理すると、アプリケーションから時間とメモリの両方を奪うことができます。このアクションは単にデータの通過に過ぎません。 – Macdiesel

+0

Railsは入力全体を解析し、すべてのパラメータを記録し、多くの100kサイズのリクエストを処理する場合、コストは莫大です。 – lzap

1

:だから

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] 

あなたはこの初期化子にハッシュを送信するために手配することができれば、あなたはデフォルトを追加したり、上書きすることができます。削除を許可するかどうかはわかりませんが、空のパーサメソッドが機能する可能性があります。

パーサはここに答える:How do I initialize ActionDispatch::ParamsParser in Rails 3.1?

コードを使用すると、JSONとしてそれを投稿し、それを期待するレールを伝える場合は、知っているactionpack-3.2.8/libに/ action_dispatch /ミドルウェア/ params_parser.rb

関連する問題