ring.middleware.format_params.cjl создает некорректный JSON
Я использую шаблон luminus с настройкой кольца / композиции / чванства.
Когда я кормлю 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 compojure.api.middleware$handle_req_error@3130fc88>}, 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 compojure.api.middleware$handle_req_error@3130fc88>}
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.
Где лучше всего попробовать / поймать?
1 ответ
Обычный способ справиться с этим - создать новое промежуточное ПО, обернуть существующее промежуточное ПО, которое улавливает ожидаемую ошибку и возвращает ваше пользовательское сообщение и статус.
(defn safe-restful-params
[handler]
(fn [request]
(try ((wrap-restful-params handler) request)
(catch IllegalArgumentException e
{:status 400 ; bad request
:body "malformed JSON"}))))
На практике вы, вероятно, захотите установить некоторые заголовки и т. Д., И вы могли бы также написать более общую версию, которая оборачивает произвольное промежуточное программное обеспечение, а не специальную оболочку для обертки этого, но это общая концепция. Промежуточное программное обеспечение вызова всегда принимает обработчик в качестве аргумента и возвращает функцию, которую вы можете вызвать по запросу вызова, и на практике обычно следует вызывать обработчик запроса как часть его выполнения. Это промежуточное ПО также вручную вставляет другое промежуточное ПО между собой и обработчиком и предназначено для замены этого другого промежуточного ПО.