2012-08-26 18 views
24

पर सिनात्रा नियंत्रक पैराम विधि खाली में आने वाली विधि मुझे एक सिनात्रा ऐप मिला है और मेरे अधिकांश नियंत्रकों में जेसन आ गया है और पैराम ऑब्जेक्ट में स्वचालित रूप से उठाया जाता है। हालांकि, मुझे एक पोस्ट एक्शन मिल गया है, जब तक कि मैं अनुरोध खींचने के लिए पहले विधि के साथ एक चाल नहीं चलाता तब तक पैराम नहीं मिलते हैं। कोई भी पैरामीटर उन्हें JSON के रूप में पार्स करता है और उन्हें पैराम्स हैश में विलय करता है।जेएसओएन पोस्ट अनुरोध

यहाँ, नियंत्रक है फिल्टर विधि के साथ:

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 

उत्पादन मैं देख रहा हूँ मूल रूप से यह है कि नियंत्रक कार्रवाई में पैरामीटर वास्तव में वहाँ सही ढंग से कर रहे हैं। हालांकि, अगर मैं पहले कॉल पर टिप्पणी करता हूं तो पैरा खाली हैं।

पहले ही एक हैक जैसा लगता है। मैं उम्मीद करता हूं कि उन परम आने से कोई फर्क नहीं पड़ता ... मुझे वहां कुछ गलत करना होगा लेकिन मुझे नहीं पता कि यह क्या है।

किसी भी मदद की गहराई से सराहना की है ...

उत्तर

31

आदेश में इस सवाल का जवाब देने के लिए, हम पहले कुछ 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 

कि चरित्र-दर-चरित्र (जो भी साथ /sample-form की जगह टाइप करना यूआरएल किसी भी फॉर्म एक्शन के लिए है, और आपके आईपी या होस्टनाम के साथ Host) वही होगा जो आपका ब्राउज़र भेजेगा। इससे सीखने की महत्वपूर्ण बात पैरामीटर सिंटैक्स है: formname=formvalueसिनात्रा POST के शरीर को इस वाक्यविन्यास का उपयोग करके params हैश में अनुरोध करता है! इसलिए, JSON अनुरोध, इसके साथ काफी असंगत होने के कारण इस कारण params हैश में दिखाई देगा।

हालांकि, आप अपने before ब्लॉक में क्या कर रहे हैं उचित समाधान दिखाता है। उपरोक्त से params{'name' => 'JohnDoe'}, request.body.read मूल निकाय, name=JohnDoe वापस कर देगा। POST अनुरोध के मूल शरीर JSON.parse से व्याख्या हो जाता है, तो खाली params हैश में डाला जाता है:

यह जानने में, एक को समझने के लिए क्यों अपने 'hacky' समाधान काम करता आ सकते हैं। ऐसा लगता है कि हैकी लगता है क्योंकि params इस उदाहरण में एक अनावश्यक मध्यस्थ है। निम्नलिखित काम करना चाहिए:

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

हालांकि, एक समाधान बेहतर अभ्यास व्यायाम या तो केवल जवाब होता अगर JSON सामग्री प्रदान की जाती है, या अलग तरीके से प्रतिक्रिया करता है, तो एक मानक फार्म प्रस्तुत किया जाता है। जैसा कि उपर्युक्त उदाहरण HTTP POST अनुरोध में देखा गया है, एक HTML फॉर्म को application/x-www-form-urlencoded MIME प्रकार के साथ पहचाना जाता है, जबकि JSON को application/json के साथ पहचाना जाता है। यदि आप POST अनुरोध के एमआईएमई प्रकार की जांच करने के बारे में विनिर्देश चाहते हैं, तो सिनात्रा के साथ ऐसा करने के तरीके पर this question with some great answers देखें!

+0

मुझे एक ही समस्या है, लेकिन आपका समाधान काम नहीं करता है: http://stackoverflow.com/posts/43336445/edit –

7

एक ऐसी ही समस्या थी: Posting JSON params from java to sinatra service

मैं, इससे निपटने के लिए मेरे लिए भी ऐसा ही करने के लिए एक मध्यस्थ जोड़कर एक बेहतर समाधान मिल गया। मैंने रैक-कॉन्ट्रिब मणि का इस्तेमाल किया। निम्न परिवर्तन मैं अपने कोड में किया था कर रहे हैं:

संपादित करें: उपयोग Git विशेष संस्करण प्राप्त करने के लिए है, जहां यह समस्या ठीक होती है जब सामग्री प्रकार application/json;charset=UTF-8

Gemfile है:

gem 'rack-contrib', git: '[email protected]:rack/rack-contrib', ref: 'b7237381e412852435d87100a37add67b2cfbb63' 

config.ru:

use Rack::PostBodyContentTypeParser 

स्रोत: http://jaywiggins.com/2010/03/using-rack-middleware-to-parse-json/

+0

धन्यवाद, महान युक्ति! –

संबंधित मुद्दे