首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我无法获得compojure-api来正确地验证带有Inst模式的查询参数的坏数据。

我无法获得compojure-api来正确地验证带有Inst模式的查询参数的坏数据。
EN

Stack Overflow用户
提问于 2018-04-26 10:48:22
回答 1查看 635关注 0票数 2

在这里,我使用metosin/compojure-api库为我的api配置了一个GET /fetch端点。您将看到,我还使用plumatic/schema来验证此端点上的查询参数输入和siilisolutions/humanize,以使任何糟糕的数据异常人性化。

代码语言:javascript
复制
(defn humanize-schema-exception [^Exception e]
  (if (instance? schema.utils.ErrorContainer (ex-data e))
    (#'humanize/explain (:error (ex-data e))
      (fn [x]
        (let [Inst java.util.Date]
          (clojure.core.match/match
            x
            ['not ['instance? Inst not-inst]]
            (str "'" not-inst "' is not a timestamp.")
            :else x))))))

(defn bad-request-handler
  "Handles bad requests."
  [f]

  (fn [^Exception e data request]
    (let [message (humanize-schema-exception e)]

      (f message))))

(def app
    (api
        {:exceptions {:handlers
                      {::ex/request-parsing    (parse-exception-handler response/bad-request)
                       ::ex/request-validation (bad-request-handler response/bad-request)
                       ::ex/default            (exception-handler response/internal-server-error)}}
         :swagger    {:ui   "/api/v1.0/docs"
                      :spec "/api/v1.0/swagger.json"}

         (GET "/fetch" []
           :query-params [{id :- schema/Int nil}
                          {timestamp_from :-  schema/Inst nil}
                          {timestamp_to :- schema/Inst nil}]
           :responses {200 {:description "ok"}
                       400 {:description "bad request"}} (foo id timestamp_from timestamo_to))))

当我提出以下请求时,端点返回200 ok。

代码语言:javascript
复制
curl -X GET --header 'Accept: application/json' 'http://localhost:3000/fetch?timestamp_from=2018-01-01T10%3A00%3A00'

但是,当使用糟糕的数据设置timestamp_from时,如下所示:

代码语言:javascript
复制
curl -X GET --header 'Accept: text/html' 'http://localhost:3000/api/v1.0/task?timestamp_from=blah%20blah%20blah'

我得到以下例外:

代码语言:javascript
复制
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* clojure.lang.ExceptionInfo: Request validation failed: {:timestamp_from (not #error {\n :cause \"Invalid format: \\\"blah blah blah\\\"\"\n :via\n [{:type java.lang.IllegalArgumentException\n   :message \"Invalid format: \\\"blah blah blah\\\"\"\n   :at [org.joda.time.format.DateTimeFormatter parseDateTime \"DateTimeFormatter.java\" 945]}]\n :trace\n [[org.joda.time.format.DateTimeFormatter parseDateTime \"DateTimeFormatter.java\" 945]\n  [clj_time.format$parse invokeStatic \"format.clj\" 160]\n  [clj_time.format$parse invoke \"format.clj\" 156]\n  [ring.swagger.coerce$parse_date_time invokeStatic \"coerce.clj\" 16]\n  [ring.swagger.coerce$parse_date_time invoke \"coerce.clj\" 16]\n  [ring.swagger.coerce$fn__13810$fn__13811 invoke \"coerce.clj\" 33]\n  [ring.swagger.coerce$coerce_if_string$fn__13807 invoke \"coerce.clj\" 31]\n  [schema.coerce$fn__13046$coercer__13051$fn__13052$fn__13053$fn__13054 invoke \"coerce.clj\" 36]\n  [schema.spec.variant.VariantSpec$fn__1808 invoke \"variant.clj\" 53]\n  [schema.spec.collection$element_transformer$fn__1842$fn__1843 invoke \"collection.clj\" 36]\n  [schema.core.MapEntry$fn__2577 invoke \"core.clj\" 766]\n  [schema.spec.collection$element_transformer$fn__1842 invoke \"collection.clj\" 36]\n  [schema.spec.collection$element_transformer$fn__1842 invoke \"collection.clj\" 36]\n  [schema.spec.collection.CollectionSpec$fn__1874 invoke \"collection.clj\" 79]\n  [schema.spec.collection$element_transformer$fn__1842$fn__1843 invoke \"collection.clj\" 36]\n  [schema.core$map_elements$iter__2602__2606$fn__2607$fn__2614 invoke \"core.clj\" 815]\n  [schema.spec.collection$element_transformer$fn__1842 invoke \"collection.clj\" 36]\n  [schema.spec.collection$element_transformer$fn__1842 invoke \"collection.clj\" 36]\n  [schema.spec.collection$element_transformer$fn__1842 invoke \"collection.clj\" 36]\n  [schema.spec.collection$element_transformer$fn__1842 invoke \"collection.clj\" 36]\n  [schema.spec.collection.CollectionSpec$fn__1874 invoke \"collection.clj\" 79]\n  [schema.coerce$fn__13046$coercer__13051$fn__13052$fn__13053$fn__13054 invoke \"coerce.clj\" 39]\n  [compojure.api.coerce$coerce_BANG_ invokeStatic \"coerce.clj\" 59]\n  [compojure.api.coerce$coerce_BANG_ invoke \"coerce.clj\" 53]\n  [app.api.handler$fn__15830$fn__15953$fn__15955 invoke \"handler.clj\" 88]\n  [compojure.core$wrap_response$fn__9969 invoke \"core.clj\" 158]\n  [compojure.core$pre_init$fn__10018 invoke \"core.clj\" 328]\n  [compojure.api.coerce$body_coercer_middleware$fn__15018 invoke \"coerce.clj\" 51]\n  [compojure.core$pre_init$fn__10020$fn__10023 invoke \"core.clj\" 335]\n  [compojure.core$wrap_route_middleware$fn__9953 invoke \"core.clj\" 127]\n  [compojure.core$wrap_route_info$fn__9958 invoke \"core.clj\" 137]\n  [compojure.core$wrap_route_matches$fn__9962 invoke \"core.clj\" 146]\n  [compojure.core$wrap_routes$fn__10030 invoke \"core.clj\" 348]\n  [compojure.api.routes.Route invoke \"routes.clj\" 74]\n  [compojure.core$routing$fn__9977 invoke \"core.clj\" 185]\n  [clojure.core$some invokeStatic \"core.clj\" 2592]\n  [clojure.core$some invoke \"core.clj\" 2583]\n  [compojure.core$routing invokeStatic \"core.clj\" 185]\n  [compojure.core$routing doInvoke \"core.clj\" 182]\n  [clojure.lang.RestFn applyTo \"RestFn.java\" 139]\n  [clojure.core$apply invokeStatic \"core.clj\" 648]\n  [clojure.core$apply invoke \"core.clj\" 641]\n  [compojure.core$routes$fn__9981 invoke \"core.clj\" 192]\n  [compojure.core$routing$fn__9977 invoke \"core.clj\" 185]\n  [clojure.core$some invokeStatic \"core.clj\" 2592]\n  [clojure.core$some invoke \"core.clj\" 2583]\n  [compojure.core$routing invokeStatic \"core.clj\" 185]\n  [compojure.core$routing doInvoke \"core.clj\" 182]\n  [clojure.lang.RestFn applyTo \"RestFn.java\" 139]\n  [clojure.core$apply invokeStatic \"core.clj\" 648]\n  [clojure.core$apply invoke \"core.clj\" 641]\n  [compojure.core$routes$fn__9981 invoke \"core.clj\" 192]\n  [compojure.core$make_context$handler__10007 invoke \"core.clj\" 285]\n  [compojure.core$make_context$fn__10009 invoke \"core.clj\" 293]\n  [compojure.api.routes.Route invoke \"routes.clj\" 74]\n  [compojure.core$routing$fn__9977 invoke \"core.clj\" 185]\n  [clojure.core$some invokeStatic \"core.clj\" 2592]\n  [clojure.core$some invoke \"core.clj\" 2583]\n  [compojure.core$routing invokeStatic \"core.clj\" 185]\n  [compojure.core$routing doInvoke \"core.clj\" 182]\n  [clojure.lang.RestFn applyTo \"RestFn.java\" 139]\n  [clojure.core$apply invokeStatic \"core.clj\" 648]\n  [clojure.core$apply invoke \"core.clj\" 641]\n  [compojure.core$routes$fn__9981 invoke \"core.clj\" 192]\n  [compojure.core$routing$fn__9977 invoke \"core.clj\" 185]\n  [clojure.core$some invokeStatic \"core.clj\" 2592]\n  [clojure.core$some invoke \"core.clj\" 2583]\n  [compojure.core$routing invokeStatic \"core.clj\" 185]\n  [compojure.core$routing doInvoke \"core.clj\" 182]\n  [clojure.lang.RestFn applyTo \"RestFn.java\" 139]\n  [clojure.core$apply invokeStatic \"core.clj\" 648]\n  [clojure.core$apply invoke \"core.clj\" 641]\n  [compojure.core$routes$fn__9981 invoke \"core.clj\" 192]\n  [compojure.core$make_context$handler__10007 invoke \"core.clj\" 285]\n  [compojure.core$make_context$fn__10009 invoke \"core.clj\" 293]\n  [compojure.api.routes.Route invoke \"routes.clj\" 74]\n  [compojure.api.core$handle$fn__15155 invoke \"core.clj\" 8]\n  [clojure.core$some invokeStatic \"core.clj\" 2592]\n  [clojure.core$some invoke \"core.clj\" 2583]\n  [compojure.api.core$handle invokeStatic \"core.clj\" 8]\n  [compojure.api.core$handle invoke \"core.clj\" 7]\n  [clojure.core$partial$fn__4759 invoke \"core.clj\" 2515]\n  [compojure.api.routes.Route invoke \"routes.clj\" 74]\n  [ring.swagger.middleware$wrap_swagger_data$fn__14533 invoke \"middleware.clj\" 35]\n  [ring.middleware.http_response$wrap_http_response$fn__12223 invoke \"http_response.clj\" 19]\n  [ring.swagger.middleware$wrap_swagger_data$fn__14533 invoke \"middleware.clj\" 35]\n  [compojure.api.middleware$wrap_options$fn__14588 invoke \"middleware.clj\" 74]\n  [ring.middleware.format_params$wrap_format_params$fn__11412 invoke \"format_params.clj\" 119]\n  [ring.middleware.format_params$wrap_format_params$fn__11412 invoke \"format_params.clj\" 119]\n  [ring.middleware.format_params$wrap_format_params$fn__11412 invoke \"format_params.clj\" 119]\n  [ring.middleware.format_params$wrap_format_params$fn__11412 invoke \"format_params.clj\" 119]\n  [ring.middleware.format_params$wrap_format_params$fn__11412 invoke \"format_params.clj\" 119]\n  [compojure.api.middleware$wrap_exceptions$fn__14578 invoke \"middleware.clj\" 43]\n  [ring.middleware.format_response$wrap_format_response$fn__12127 invoke \"format_response.clj\" 194]\n  [ring.middleware.keyword_params$wrap_keyword_params$fn__12253 invoke \"keyword_params.clj\" 36]\n  [ring.middleware.nested_params$wrap_nested_params$fn__12293 invoke \"nested_params.clj\" 89]\n  [ring.middleware.params$wrap_params$fn__12341 invoke \"params.clj\" 67]\n  [compojure.api.middleware$wrap_options$fn__14588 invoke \"middleware.clj\" 74]\n  [compojure.api.routes.Route invoke \"routes.clj\" 74]\n  [ring.logger$wrap_with_logger_STAR_$fn__449 invoke \"logger.clj\" 19]\n  [ring.logger$wrap_request_start$fn__453 invoke \"logger.clj\" 37]\n  [app.api.handler$with_request_id$fn__15574 invoke \"handler.clj\" 39]\n  [ring.adapter.jetty$proxy_handler$fn__16412 invoke \"jetty.clj\" 25]\n  [ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a handle nil -1]\n  [org.eclipse.jetty.server.handler.HandlerWrapper handle \"HandlerWrapper.java\" 97]\n  [org.eclipse.jetty.server.Server handle \"Server.java\" 499]\n  [org.eclipse.jetty.server.HttpChannel handle \"HttpChannel.java\" 311]\n  [org.eclipse.jetty.server.HttpConnection onFillable \"HttpConnection.java\" 258]\n  [org.eclipse.jetty.io.AbstractConnection$2 run \"AbstractConnection.java\" 544]\n  [org.eclipse.jetty.util.thread.QueuedThreadPool runJob \"QueuedThreadPool.java\" 635]\n  [org.eclipse.jetty.util.thread.QueuedThreadPool$3 run \"QueuedThreadPool.java\" 555]\n  [java.lang.Thread run \"Thread.java\" 745]]})} schema.utils.ErrorContainer@d7238842
*/

我还希望看到更多这样的东西:

代码语言:javascript
复制
clojure.lang.ExceptionInfo: Request validation failed {:timestamp_from (not (instance? java.util.Date \"blah blah blah\"))}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-27 11:50:18

这是ring-swagger中的一个特性/bug,它正在执行字符串->日期转换。它应该捕获解析异常并发出更好的错误,但不会。

来源:https://github.com/metosin/ring-swagger/blob/dec51a0750535f0453cbf7d6574bd1783c9bf6a1/src/ring/swagger/coerce.clj#L31-L36

你可以提交一个问题或者做一个公关来解决这些问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50041066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档