4

API 전용 Rails 5.x 애플리케이션에 대해 조작 된 JSON을 보낼 때마다 예외가 발생하고 레일스가 전체 스택 추적을 JSON으로 리턴합니다. 분명히 정중하고 맞춤 설정된 형식의 오류로 응답하고 싶습니다.ActionDispatch :: ParamsParser :: ParseError를 구하고 레일 5에서 맞춤 API 오류를 반환하는 방법은 무엇입니까?

=> Booting Puma 
=> Rails 5.0.0.1 application starting in development on http://localhost:3000 
=> Run `rails server -h` for more startup options 
Puma starting in single mode... 
* Version 3.6.0 (ruby 2.3.0-p0), codename: Sleepy Sunday Serenity 
* Min threads: 5, max threads: 5 
* Environment: development 
* Listening on tcp://localhost:3000 
Use Ctrl-C to stop 
Started POST "/api/v1/identities/" for ::1 at 2016-10-26 18:42:32 +0200 
    ActiveRecord::SchemaMigration Load (0.3ms) SELECT "schema_migrations".* FROM "schema_migrations" 
Error occurred while parsing request parameters. 
Contents: 

{ 
    "whatever": "ewewgewewtwe" 
    "malformed_json": "; 
} 

ActionDispatch::ParamsParser::ParseError (822: unexpected token at '{ 
    "whatever": "ewewgewewtwe" 
    "malformed_json": "; 
}'): 

actionpack (5.0.0.1) lib/action_dispatch/http/parameters.rb:71:in `rescue in parse_formatted_parameters' 
actionpack (5.0.0.1) lib/action_dispatch/http/parameters.rb:65:in `parse_formatted_parameters' 
actionpack (5.0.0.1) lib/action_dispatch/http/request.rb:366:in `block in POST' 
rack (2.0.1) lib/rack/request.rb:57:in `fetch' 
rack (2.0.1) lib/rack/request.rb:57:in `fetch_header' 
actionpack (5.0.0.1) lib/action_dispatch/http/request.rb:365:in `POST' 
actionpack (5.0.0.1) lib/action_controller/metal/params_wrapper.rb:282:in `_wrapper_enabled?' 
actionpack (5.0.0.1) lib/action_controller/metal/params_wrapper.rb:231:in `process_action' 
activerecord (5.0.0.1) lib/active_record/railties/controller_runtime.rb:18:in `process_action' 
actionpack (5.0.0.1) lib/abstract_controller/base.rb:126:in `process' 
actionpack (5.0.0.1) lib/action_controller/metal.rb:190:in `dispatch' 
actionpack (5.0.0.1) lib/action_controller/metal.rb:262:in `dispatch' 
actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb:50:in `dispatch' 
actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb:32:in `serve' 
actionpack (5.0.0.1) lib/action_dispatch/journey/router.rb:39:in `block in serve' 
actionpack (5.0.0.1) lib/action_dispatch/journey/router.rb:26:in `each' 
actionpack (5.0.0.1) lib/action_dispatch/journey/router.rb:26:in `serve' 
actionpack (5.0.0.1) lib/action_dispatch/routing/route_set.rb:725:in `call' 
rack (2.0.1) lib/rack/etag.rb:25:in `call' 
rack (2.0.1) lib/rack/conditional_get.rb:38:in `call' 
rack (2.0.1) lib/rack/head.rb:12:in `call' 
activerecord (5.0.0.1) lib/active_record/migration.rb:552:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call' 
activesupport (5.0.0.1) lib/active_support/callbacks.rb:97:in `__run_callbacks__' 
activesupport (5.0.0.1) lib/active_support/callbacks.rb:750:in `_run_call_callbacks' 
activesupport (5.0.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/callbacks.rb:36:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/remote_ip.rb:79:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call' 
railties (5.0.0.1) lib/rails/rack/logger.rb:36:in `call_app' 
railties (5.0.0.1) lib/rails/rack/logger.rb:24:in `block in call' 
activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:70:in `block in tagged' 
activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:26:in `tagged' 
activesupport (5.0.0.1) lib/active_support/tagged_logging.rb:70:in `tagged' 
railties (5.0.0.1) lib/rails/rack/logger.rb:24:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/request_id.rb:24:in `call' 
rack (2.0.1) lib/rack/runtime.rb:22:in `call' 
activesupport (5.0.0.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call' 
actionpack (5.0.0.1) lib/action_dispatch/middleware/static.rb:136:in `call' 
rack (2.0.1) lib/rack/sendfile.rb:111:in `call' 
railties (5.0.0.1) lib/rails/engine.rb:522:in `call' 
puma (3.6.0) lib/puma/configuration.rb:225:in `call' 
puma (3.6.0) lib/puma/server.rb:578:in `handle_request' 
puma (3.6.0) lib/puma/server.rb:415:in `process_client' 
puma (3.6.0) lib/puma/server.rb:275:in `block in run' 
puma (3.6.0) lib/puma/thread_pool.rb:116:in `block in spawn_thread' 

는 이전에 나는 다음과 같은 예외를 미들웨어를 추가하고 처리 할 수 ​​생각 : 미들웨어 ActionDispatch::ParamsError가 레일 (5)에서 제거 된 것으로 보인다 그러나

# in config/application.rb 

config.middleware.insert_before(ActionDispatch::ParamsError,'BadRequestError') 

# middleware 

class BadRequestError 
    def initialize(app) 
     @app = app 
    end 

    def call(env) 
     begin 
      @app.call(env) 
     rescue ActionDispatch::ParamsParser::ParseError 
      Api::ApiController.action(:raise_bad_request).call(env) 
     end 
    end 
end 

을;

다른 미들웨어 (예 : ActionDispatch :: ShowExceptions)를 사용해도 다른 오류를 해결하려고했지만 내 raise_bad_request 동작이 어떻게 든 호출되지 않습니다.

뭔가 잘못되었거나 잘못되었거나 레일스 5에서 다른 방법이 있습니까?

감사합니다.

답변

8

답변이 Rails 5.1 이상에서 작동하도록 업데이트되었습니다. (Thanks @Edwin Meyer) config.middlware.use에는 문자열 대신 클래스가 필요합니다.

나는 이제 미시적 도구를 app/middleware 아래에 넣었다고 언급합니다. 그래서 필요가 없습니다.


나는 동일한 문제가 있었으며, 내 경우에는 해결하기가 매우 간단했습니다.

그냥 application.rb에서 사용 : 다음

# 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 

을 내가 잘못된 JSON을 보낼 때 응답은 다음과 같습니다 :

config.middleware.use CatchJsonParseErrors 

# Instead of 
# config.middleware.insert_before ActionDispatch::ParamsParser, "CatchJsonParseErrors" 
# I used in my Rails 4 app 

내 미들웨어 (Catching Invalid JSON Parse Errors with Rack Middleware에서) 다음과 같습니다

{"status":400,"error":"There was a problem in the JSON you submitted: 743: unexpected token at '{ \"foo\": \"bar\" '"} 

올바른 012를 제공해야합니다.헤더.

희망도 도움이됩니다.

2

나는 레일 5.1.4을 실행하고, 나는 나를 위해 작동하는 스파의 솔루션을 얻을하는 데 필요한 다음과 같은 수정 발견 : application.rb에서

-

1) config.middleware하는 인수 config.middleware.use CatchJsonParseErrors
2) catch_json_parse_errors.rb이 필요합니다 : catch_json_parse_errors에서
require './app/middleware/catch_json_parse_errors'

.use는 클래스가 아닌 문자열이 될 것으로 보인다.RB -
변경 CONTENT_TYPE하지만 HTTP_ACCEPT도 처리 지정
if env['HTTP_ACCEPT'] =~ /application\/json/ || env['CONTENT_TYPE'] =~ /application\/json/
그렇게 나쁜 콘텐츠는 HTTP 요청에 선
if env['HTTP_ACCEPT'] =~ /application\/json/
.