2015-08-24 6 views
1

Я использую шаблон luminus с настройкой ring/compojure/swagger.ring.middleware.format_params.cjl throws on malformed JSON

Когда кормлю REST API Я создал искаженный JSON я получаю 500 и:

java.lang.IllegalArgumentException: No value supplied for key: {:formats (:json-kw :yaml-kw :edn :transit-json :transit-msgpack), :handle-error #<middleware$handle_req_error [email protected]>}, compiling:(pythonapi.clj:14:1) 
    at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3558) 
    at clojure.lang.Compiler$DefExpr.eval(Compiler.java:417) 
    at clojure.lang.Compiler.eval(Compiler.java:6708) 
    at clojure.lang.Compiler.load(Compiler.java:7130) 
    at clojure.lang.RT.loadResourceScript(RT.java:370) 
    at clojure.lang.RT.loadResourceScript(RT.java:361) 
    at clojure.lang.RT.load(RT.java:440) 
    at clojure.lang.RT.load(RT.java:411) 
    at clojure.core$load$fn__5066.invoke(core.clj:5641) 
    at clojure.core$load.doInvoke(core.clj:5640) 
    at clojure.lang.RestFn.invoke(RestFn.java:408) 
    at clojure.core$load_one.invoke(core.clj:5446) 
    at clojure.core$load_lib$fn__5015.invoke(core.clj:5486) 
    at clojure.core$load_lib.doInvoke(core.clj:5485) 
    at clojure.lang.RestFn.applyTo(RestFn.java:142) 
    at clojure.core$apply.invoke(core.clj:626) 
    at clojure.core$load_libs.doInvoke(core.clj:5524) 
    at clojure.lang.RestFn.applyTo(RestFn.java:137) 
    at clojure.core$apply.invoke(core.clj:626) 
    at clojure.core$require.doInvoke(core.clj:5607) 
    at clojure.lang.RestFn.invoke(RestFn.java:1289) 
    at voicepin_collector.handler$eval23$loading__4958__auto____24.invoke(handler.clj:1) 
    at voicepin_collector.handler$eval23.invoke(handler.clj:1) 
    at clojure.lang.Compiler.eval(Compiler.java:6703) 
    at clojure.lang.Compiler.eval(Compiler.java:6692) 
    at clojure.lang.Compiler.load(Compiler.java:7130) 
    at clojure.lang.RT.loadResourceScript(RT.java:370) 
    at clojure.lang.RT.loadResourceScript(RT.java:361) 
    at clojure.lang.RT.load(RT.java:440) 
    at clojure.lang.RT.load(RT.java:411) 
    at clojure.core$load$fn__5066.invoke(core.clj:5641) 
    at clojure.core$load.doInvoke(core.clj:5640) 
    at clojure.lang.RestFn.invoke(RestFn.java:408) 
    at clojure.core$load_one.invoke(core.clj:5446) 
    at clojure.core$load_lib$fn__5015.invoke(core.clj:5486) 
    at clojure.core$load_lib.doInvoke(core.clj:5485) 
    at clojure.lang.RestFn.applyTo(RestFn.java:142) 
    at clojure.core$apply.invoke(core.clj:626) 
    at clojure.core$load_libs.doInvoke(core.clj:5524) 
    at clojure.lang.RestFn.applyTo(RestFn.java:137) 
    at clojure.core$apply.invoke(core.clj:626) 
    at clojure.core$require.doInvoke(core.clj:5607) 
    at clojure.lang.RestFn.invoke(RestFn.java:408) 
    at voicepin_collector.listener$_contextInitialized.invoke(listener.clj:1) 
    at voicepin_collector.listener.contextInitialized(Unknown Source) 
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973) 
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467) 
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) 
    at org.apache.catalina.manager.ManagerServlet.start(ManagerServlet.java:1291) 
    at org.apache.catalina.manager.HTMLManagerServlet.start(HTMLManagerServlet.java:694) 
    at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:217) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:646) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.apache.catalina.filters.CsrfPreventionFilter.doFilter(CsrfPreventionFilter.java:213) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:610) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.lang.IllegalArgumentException: No value supplied for key: {:formats (:json-kw :yaml-kw :edn :transit-json :transit-msgpack), :handle-error #<middleware$handle_req_error [email protected]>} 
    at clojure.lang.PersistentHashMap.create(PersistentHashMap.java:77) 
    at ring.middleware.format_params$wrap_restful_params.doInvoke(format_params.clj:251) 
    at clojure.lang.RestFn.invoke(RestFn.java:423) 
    at compojure.api.middleware$api_middleware.doInvoke(middleware.clj:214) 
    at clojure.lang.RestFn.invoke(RestFn.java:423) 
    at compojure.api.core$api_middleware_with_routes.invoke(core.clj:21) 
    at clojure.lang.AFn.applyToHelper(AFn.java:156) 
    at clojure.lang.AFn.applyTo(AFn.java:144) 
    at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3553) 
    ... 78 more 

Я считаю, что я должен перехватить это исключение для того, чтобы информировать пользователя о том, с искаженной JSON был отправлен и вернуться 400.

Где лучше всего выполнить try/catch?

ответ

1

Обычный способ, с которым я обращаюсь, заключается в создании нового промежуточного программного обеспечения, обертывания существующего промежуточного программного обеспечения, которое ловит ожидаемую ошибку и возвращает ваше пользовательское сообщение и статус.

(defn safe-restful-params 
    [handler] 
    (fn [request] 
    (try ((wrap-restful-params handler) request) 
     (catch IllegalArgumentException e 
      {:status 400 ; bad request 
      :body "malformed JSON"})))) 

На практике вы, вероятно, хотите установить некоторые заголовки и т.д., и вы также можете написать более общую версию, которая оборачивает произвольные промежуточную программное обеспечение вместо специального кожуха оборачивания этого, но это общее понятие. Кольцевое промежуточное ПО всегда принимает обработчик в качестве своего аргумента и возвращает функцию, которую вы можете вызывать на запрос звонка, и на практике обычно должен вызывать обработчик запроса, как часть его выполнения. Это промежуточное программное обеспечение также вручную вставляет другое промежуточное ПО между собой и обработчиком и предназначено для замены этого другого промежуточного программного обеспечения.

+0

PS. Я определил, какое промежуточное программное обеспечение выбрасывает исключение из трассировки стека, не стесняйтесь при необходимости корректировать этот код, если я неверно идентифицировал промежуточное программное обеспечение, которое приводит к этому исключению. Может быть, это на самом деле 'format-params'? – noisesmith