2013-06-11 5 views
21

Sto scrivendo un'API e riceve un carico utile JSON come corpo della richiesta.Come analizzare il corpo della richiesta JSON in Sinatra solo una volta e esporlo a tutte le rotte?

per arrivare a esso attualmente, sto facendo qualcosa di simile:

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

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

Che cosa è un buon modo per astrarre questa via in modo che non ho bisogno di farlo per ogni itinerario? Alcuni dei miei percorsi sono più complicati di questo e, di conseguenza, la richiesta. Qualcuno verrebbe riletto e riorganizzato più volte per percorso con questo approccio, che voglio evitare.

C'è un modo per rendere il request_payload semplicemente magicamente disponibile per le rotte? Come questo:

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

risposta

46

Utilizzare un Sinatra prima di handler:

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

questo esporlo al gestore di richiesta corrente. Se vuoi che venga esposto a tutti i gestori, inseriscilo in una superclasse e estendi quella classe nei tuoi gestori.

+0

Questo è stato il mio primo istinto, ma funziona con async-sinatra? Temo che le richieste successive potrebbero annullarlo mentre quelle precedenti sono ancora in volo? – lms

+1

Sinatra * dovrebbe * creare una nuova istanza di ciascun gestore per richiesta, quindi a condizione che si utilizzi una variabile a livello di istanza dovrebbe essere ok. Usiamo uno schema simile e non abbiamo visto prove di condizioni di gara sotto carico. – mcfinnigan

+0

Il filtro 'before' [può essere] (http://www.sinatrarb.com/intro.html#Filters) basato su pattern di route ma apparentemente non su metodi HTTP. Bummer: fare questo solo per i POST è un caso d'uso plausibile. – mgold

1

come non lavorare per Sinatra 1.4.5

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

È inoltre possibile utilizzare Rack Middleware per analizzarlo. Vedi https://github.com/rack/rack-contrib Appena use Rack::PostBodyContentTypeParser durante l'inizializzazione della tua classe Sinatra.

Problemi correlati