Sinatra controller méthode params à venir vide sur demande de JSON post
J'ai une application Sinatra et dans la plupart de mes contrôleurs json est entré et est repris automatiquement dans l'objet params. Cependant, j'ai une action de poste qui n'obtient pas les params du tout à moins que je joue un tour avec une méthode avant de tirer la demande.les paramètres du corps les analysent comme JSON et les fusionnent dans le hash des params.
voici le contrôleur, ainsi que la méthode du filtre:
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
la sortie que je vois est essentiellement que le les paramètres du contrôleur d'action sont là correctement. Cependant, si je commente l'appel avant les params sont vides.
l'avant lui-même se sent comme un piratage. Je les params de venir dans n'importe quoi...Je dois faire quelque chose de mal, mais je ne sais pas ce que c'est.
Toute aide serait grandement appréciée...
2 réponses
pour répondre à cette question, nous allons d'abord devoir regarder quelques requêtes HTTP (qui ne sont pas plus que de simples" messages " 151920920; cela peut facilement être recréé à la main). Tout d'abord, que se passe-t-il lorsque vous soumettez un HTML normal <form>
? La requête POST
ressemblera beaucoup à celle-ci (probablement avec quelques paramètres supplémentaires, mais nous n'avons pas besoin de nous en inquiéter pour le moment):
POST /submit-form HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
name=JohnDoe
tapant ce caractère par caractère (en remplaçant le /sample-form
par n'importe quelle URL pour n'importe quelle action de forme, et le Host
par votre IP ou nom d'hôte) sera la même chose que votre navigateur enverrait. La chose importante à savoir, c'est la syntaxe de paramètre: formname=formvalue
. Sinatra interprète le corps de la requête POST
dans le hash params
en utilisant cette syntaxe! par conséquent, les demandes de JSON, étant essentiellement incompatible avec ce, sera et non apparaître dans le params
hachage à cause de cela.
cependant, ce que vous faites dans votre bloc before
montre la bonne solution. Alors que params
de ce qui précède serait {'name' => 'JohnDoe'}
, request.body.read
retournera le corps original, name=JohnDoe
.
en sachant cela, on peut en venir à comprendre pourquoi votre solution' hacky 'fonctionne: le corps original de la requête POST
est interprété par JSON.parse
, puis est inséré dans le vide params
de hachage. La raison pour laquelle il semble hacky est parce que params
est un intermédiaire inutile dans cet exemple. Le suivant devrait faire le travail:
post '/locations/new' do
@json = JSON.parse(request.body.read)
# @json now contains a hash of the submitted JSON content
end
cependant, une solution faisant appel à une meilleure pratique ne répondrait que si le contenu JSON était fourni, ou répondrait différemment si un formulaire standard était soumis. Comme le montre L'exemple ci-dessus de requête HTTP POST
, un formulaire HTML est identifié avec le type MIME application/x-www-form-urlencoded
, tandis que JSON est identifié avec application/json
. Si vous voulez les détails sur la vérification du type MIME de la demande POST
, consultez cette question avec quelques grandes réponses sur la façon de faire cela avec Sinatra!
avait un problème similaire: Affichage JSON params de java à sinatra service
j'ai trouvé une meilleure solution pour y faire face, en ajoutant un middleware pour faire la même chose pour moi. J'ai utilisé du rack-contrib gem. Voici les changements que j'ai faits dans mon code:
EDIT: utiliser git pour obtenir la version spécifique, où il résout le problème lorsque le contenu est de type application/json;charset=UTF-8
Gemfile:
gem 'rack-contrib', git: 'git@github.com:rack/rack-contrib', ref: 'b7237381e412852435d87100a37add67b2cfbb63'
config.ru:
use Rack::PostBodyContentTypeParser
source: http://jaywiggins.com/2010/03/using-rack-middleware-to-parse-json /