Compojure-api:请求强制通过multipart-params提供的地图

时间:2018-06-29 15:45:52

标签: clojure compojure compojure-api

我正在尝试将compojure-api(版本1.1.12)集成到现有的基于compojure的应用程序中。尽管大多数事情都可以正常工作,但是我对现有REST调用的请求强制性存在问题,此时其用法将很难更改。

  • 这是POST
  • 它希望通过multipart / form-data提供参数
  • 大多数参数是可选的。
  • 大多数参数很简单:字符串或字符串数​​组。
  • 一个可选参数应该是JSON编码的地图。

我这样定义路线:

(POST "/endpoint" request
    :multipart-params 
        [required-strings :- (describe [s/Str] "Required, an array of strings"),
         {optional-string :- (describe s/Str "An optional string") ""},
         {others :- {s/Keyword s/Any} {}}]
    ...)

这有效,除非我尝试在请求中传递other-parameters。例如,通过curl:

curl -F "required-strings=[\"Hello\"]" -F "others={\"a\":1.0}" ...

这会导致内容的无效请求(即状态400)错误:

{"errors":{"others":"(not (map? a-clojure.lang.PersistentVector))"}}

我使用的是默认铃声site-defaults,并且没有修改compojure api的默认强制。我已将错误跟踪到compojure.api.coerce/coerce。我可以看到强制程序正在处理的值,它看起来像:

{:required-strings "[\"Hello\"]"
 :others "{\"a\":1.0}"}

在coerce.clj的第59行上,(coerce value)返回一个错误(每个schema.utils/error?)。

那么,是否不可能将JSON编码的多部分参数强制转换为Clojure映射?我可以将参数定义为字符串而不是映射,然后自己进行解析,但这违反了使用compojure-api和ring-swagger的目的。

1 个答案:

答案 0 :(得分:1)

others的强制转换符期望clojure映射而不是字符串。要使其工作,您必须选择。

第一个选择:添加wrap-json-params中间件并执行application/json而不是multipart/form-data的请求:

curl ... -H 'Content-Type: application/json' \
     -d $'{
  "required-strings": ["Hello"],
  "others": {"a": 1.0}
}'

第二个选项:使用嵌套的参数名称添加wrap-nested-params中间件和multipart/form-data请求:

curl ... -H 'Content-Type: multipart/form-data' \
     -F "required-strings[]=Hello" \
     -F "others[a]=1.0"