27

私は Sinatra アプリを持っており、ほとんどのコントローラーで json が入ってきて、params オブジェクトで自動的に取得されます。ただし、request.bodyパラメーターをJSONとして解析し、paramsハッシュにマージする前にメソッドを使用してトリックをしない限り、パラメーターをまったく取得しないポストアクションがあります。

以下はコントローラーと filter メソッドです。

before do
  if request.request_method == "POST"
    body_parameters = request.body.read
    params.merge!(JSON.parse(body_parameters))
  end
end


post '/locations/new' do
  content_type :json
  puts "params after post params method = #{params.inspect}"
  ... other code ...
end

私が見る出力は、基本的に、コントローラーアクションのパラメーターが実際に正しくそこにあるということです。ただし、 before 呼び出しをコメントアウトすると、パラメーターは空になります。

ビフォア自体はハックのように感じます。私はそれらのパラメーターが何があっても入ってくることを期待しています...私はそこで何か間違ったことをしているに違いありませんが、それが何であるかわかりません。

どんな助けでも大歓迎です...

4

3 に答える 3

36

この質問に答えるために、まずいくつかの HTTP リクエストを調べる必要があります (これは単純なtelnet「メッセージ」にすぎません。これは手動で簡単に再作成できます)。まず、通常の HTML を送信するとどうなります<form>か? リクエストはこれPOSTと非常によく似たものになります (おそらくいくつかのパラメーターが追加されていますが、今は気にする必要はありません)。

POST /submit-form HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12

name=JohnDoe

その文字を 1 文字ずつ入力する ( を/sample-formフォーム アクションの URL に置き換え、 をHostIP またはホスト名に置き換える) と、ブラウザーが送信するものと同じになります。これから学ぶべき重要なことは、パラメーターの構文です: formname=formvalue. Sinatra は、この構文を使用してリクエストの本文をハッシュに解釈します! POSTparamsしたがって、これと実質的に互換性のない JSON リクエストは、このためハッシュに表示されません。params

ただし、beforeブロックで行っていることは、適切な解決策を示しています。上記paramsから になりますが{'name' => 'JohnDoe'}request.body.read元の本体を返しname=JohnDoeます。

これを知ることで、あなたの「ハック」ソリューションが機能する理由を理解できるようになります。POSTリクエストの元の本文が によって解釈され、空のハッシュJSON.parseに挿入されます。paramsハックに見える理由paramsは、この例では不必要な仲介者だからです。以下は仕事をするべきです:

post '/locations/new' do
    @json = JSON.parse(request.body.read)
    # @json now contains a hash of the submitted JSON content
end

ただし、より良いプラクティスを実行するソリューションは、JSON コンテンツが提供された場合にのみ応答するか、標準フォームが送信された場合に異なる応答を返します。上記の HTTPPOSTリクエストの例に見られるように、HTML フォームはapplication/x-www-form-urlencodedMIME タイプで識別されますが、JSON は で識別されapplication/jsonます。POSTリクエストの MIME タイプの確認に関する詳細が必要な場合は、この質問をチェックして、Sinatra でこれを行う方法に関するいくつかの優れた回答を確認してください!

于 2012-08-27T08:46:57.450 に答える
15

同様の問題がありました: JavaからsinatraサービスへのJSONパラメータの投稿

同じことをするミドルウェアを追加することで、それに対処するためのより良い解決策を見つけました。Rack-contrib gem を使用しました。以下は、コードで行った変更です。

編集: git を使用して特定のバージョンを取得し、コンテンツ タイプが次の場合の問題を修正します。application/json;charset=UTF-8

Gemfile:

gem 'rack-contrib', git: 'git@github.com:rack/rack-contrib', ref: 'b7237381e412852435d87100a37add67b2cfbb63'

config.ru:

use Rack::PostBodyContentTypeParser

ソース: https://www.jaywiggins.com/2010/03/29/Using-Rack-middleware-to-parse-JSON/

于 2012-09-02T08:17:17.660 に答える