2015-03-02 14 views
5

Primo:Uva: Salvataggio da JSON valido

sto usando uva per costruire il mio API (Rails 4). Quando qualcuno sta inviando un corpo di JSON valido (per esempio dimenticato l'ultimo }), il seguente errore viene generato:

ActionDispatch::ParamsParser::ParseError (795: unexpected token at '{"foobar": 1234 

') 

ho provato con l'uva rescue_from :all opzione, ma questo non funziona. All'interno dello stacktrace, non vedo la gemma dell'uva coinvolta. Sembra che questo errore viene generato da actionpack:

.gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:53:in `rescue in parse_formatted_parameters' 
    .gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:32:in `parse_formatted_parameters' 
    .gems/gems/actionpack-4.1.4/lib/action_dispatch/middleware/params_parser.rb:23:in `call' 

Ma quale sarebbe il modo migliore per catturare quegli errori, restituire un 400: Bad Request errori, e includere il messaggio unexpected token at '{"foobar": 1234 all'interno della risposta JSON?

Secondo:

Ho provato a testare questo con RSpec, ma non ha avuto fortuna su inviando una richiesta greggio avente un JSON valido. Ho provato con

post "/my_route", '{some invalid json' 

ma questo non genera l'errore dall'alto. Ho pensato che dal momento che Rails 4, il secondo parametro, passato come una stringa, è trattato come il corpo grezzo?

+0

Credo che si dovrebbe considerare che separa questa domanda in due domande ... –

risposta

4

Sfortunatamente ActionDispatch gira molto prima di arrivare a un controller in modo da non poterlo fare con Grape (AFAIK).

Ci siamo imbattuti in questo problema e abbiamo trovato un wonderful article dai ragazzi di Thoughtbot sull'argomento.

Utilizzare la gemma Curb per effettuare le chiamate per ferite:

require 'curb' 
it 'sends poorly formatted json' do 
    broken_json = %Q|{"notice":{"title":"A sweet title"#{invalid_tokens}}}| 
    resp = Curl.post("http://#{host}:#{port}#{path}", broken_json) 

    expect(resp.response_code).to eq 500 
end 

Thoughtbot consiglia di scrivere una classe middleware per catturare futuro JSON errori di analisi in questo modo:

# in app/middleware/catch_json_parse_errors.rb 
class CatchJsonParseErrors 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    begin 
     @app.call(env) 
    rescue ActionDispatch::ParamsParser::ParseError => error 
     if env['HTTP_ACCEPT'] =~ /application\/json/ 
     error_output = "There was a problem in the JSON you submitted: #{error}" 
     return [ 
      400, { "Content-Type" => "application/json" }, 
      [ { status: 400, error: error_output }.to_json ] 
     ] 
     else 
     raise error 
     end 
    end 
    end 
end 
+0

Grazie, ci provo! Ancora una domanda: non ho capybara in esecuzione, uso solo rspec 'type:: request' specs. Come posso trovare l'host corrente (dovrebbe essere localhost) e port? – 23tux

+0

Imposterei una costante nel proprio 'spec_helper' per l'host (uguale a localhost). – Anthony

+0

Ok, l'host è chiaro, ma per quanto riguarda la porta? C'è un modo per scoprire, su quale porta rspec sta correndo rotaie? – 23tux

Problemi correlati