Compojure-api: запрос приведения для карты, предоставленной через multipart-params
Я пытаюсь интегрировать compojure-api (версия 1.1.12) в существующее приложение, основанное на compojure. Хотя большинство вещей работает, у меня возникла проблема с приведениями запросов к существующему вызову REST, использование которого было бы трудно изменить на данном этапе.
- Это ПОСТ
- Ожидает параметры через 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
, и я не изменил принуждения по умолчанию для API compojure. Я проследил ошибку compojure.api.coerce/coerce
, Я вижу значение, над которым работает coercer, и это выглядит так:
{:required-strings "[\"Hello\"]"
:others "{\"a\":1.0}"}
В строке 59 coerce.clj, (coerce value)
возвращает ошибку (за schema.utils/error?
).
Итак, нельзя ли принудительно включить JSON-закодированный многокомпонентный параметр в карту Clojure? Я могу определить параметр как строку вместо карты и выполнить синтаксический анализ самостоятельно, но это противоречит цели использования compojure-api и ring-swagger.
1 ответ
Привязка для others
ожидает карту замыкания, а не строку. Чтобы это работало, у вас есть варианты.
Первый вариант: добавить промежуточное ПО 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"