2013-06-11 6 views
21

Piszę API i otrzymuje on ładunek JSON jako ciało żądania.Jak analizować treść żądania JSON w Sinatrze tylko raz i wystawiać ją na wszystkie trasy?

Aby dostać się na nim obecnie robie coś takiego:

post '/doSomething' do 
    request.body.rewind 
    request_payload = JSON.parse request.body.read 

    #do something with request_payload 
    body request_payload['someKey'] 
end 

Co to dobry sposób abstrakcyjny to z dala tak, że nie muszę tego robić dla każdej drogi? Niektóre z moich tras są bardziej skomplikowane, w wyniku czego request.body zostanie ponownie odczytany i ponownie wykonany kilka razy na trasie z tym podejściem, którego chcę uniknąć.

Czy jest jakiś sposób na to, aby request_payload było magicznie dostępne dla tras? Tak:

post '/doSomething' do 
    #do something with request_payload, it's already parsed and available 
    body request_payload['someKey'] 
end 

Odpowiedz

46

Użyj Sinatrę przed obsługi:

before do 
    request.body.rewind 
    @request_payload = JSON.parse request.body.read 
end 

to narazi go do bieżącej obsługi żądania. Jeśli chcesz, aby był on dostępny dla wszystkich programów obsługi, umieść go w superklasie i rozszerz tę klasę w programach obsługi.

+0

To był mój pierwszy instynkt, ale czy to zadziała z async-sinatrą? Obawiam się, że kolejne wnioski mogą go zastąpić, podczas gdy poprzednie wciąż są w trakcie lotu? – lms

+1

Sinatra * powinien * utworzyć nową instancję każdego programu obsługi na żądanie, więc pod warunkiem, że używasz zmiennej poziomu instancji, powinno być w porządku. Używamy podobnego schematu i nie widzimy dowodów na warunki wyścigu pod obciążeniem. – mcfinnigan

+0

Filtr "before" [może być] (http://www.sinatrarb.com/intro.html#Filters) przewidywał wzorce tras, ale pozornie nie był to metoda HTTP. Bummer - robienie tego tylko dla POST jest prawdopodobnym przypadkiem użycia. – mgold

1

Jak to działa dla Sinatra 1.4.5

before do 
    if request.body.size > 0 
    request.body.rewind 
    @params = ActiveSupport::JSON.decode(request.body.read) 
    end 
end 
7

Można również użyć go do stojaka Middleware analizowania. Zobacz https://github.com/rack/rack-contrib Po prostu use Rack::PostBodyContentTypeParser podczas inicjowania twojej klasy Sinatra.

Powiązane problemy