Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Malli coercion incorrectly rejects [:or [:map ...] [:map ...]] #407

Closed
crclark opened this issue May 22, 2020 · 2 comments · Fixed by metosin/malli#201 or #408
Closed

Malli coercion incorrectly rejects [:or [:map ...] [:map ...]] #407

crclark opened this issue May 22, 2020 · 2 comments · Fixed by metosin/malli#201 or #408
Labels

Comments

@crclark
Copy link

crclark commented May 22, 2020

If I specify that a POST or PUT body should conform to either of two :map schemata, the malli coercion middleware incorrectly rejects both.

Working from the ring-malli-swagger example, with this patch:

--- a/examples/ring-malli-swagger/src/example/server.clj
+++ b/examples/ring-malli-swagger/src/example/server.clj
@@ -16,8 +16,13 @@
             [ring.adapter.jetty :as jetty]
             [muuntaja.core :as m]
             [clojure.java.io :as io]
+            [malli.core :as malli]
             [malli.util :as mu]))
 
+(def or-maps-schema
+  (malli/schema
+   [:or [:map [:x int?]] [:map [:y int?]]]))
+
 (def app
   (ring/ring-handler
     (ring/router
@@ -66,7 +71,15 @@
                  :responses {200 {:body [:map [:total int?]]}}
                  :handler (fn [{{{:keys [x y]} :body} :parameters}]
                             {:status 200
-                             :body {:total (+ x y)}})}}]]]
+                             :body {:total (+ x y)}})}}]]
+
+       ["/ormaps"
+        {:post {:summary "accepts either of two map schemas"
+                :parameters {:body or-maps-schema}
+                :responses {200 {:body [:map [:msg string?]]}}
+                :handler (fn [{{{:keys [x y]} :body} :parameters}]
+                           {:status 200
+                            :body {:msg (if x "you sent x" "you sent y")}})}}]]
 
       {;;:reitit.middleware/transform dev/print-request-diffs ;; pretty diffs
        ;;:validate spec/validate ;; enable spec validation for route data
-- 

In the repl, I can see that both maps are accepted by malli.core/validate, as I expect:

example.server=> (require '[malli.core :as m])
nil
example.server=> (m/validate or-maps-schema {:x 1})
true
example.server=> (m/validate or-maps-schema {:y 1})
true
example.server=> (malli/validate or-maps-schema {:z 1})
false

However, if I POST, I get a 400 response:

➜ http POST :3000/ormaps x:=1
HTTP/1.1 400 Bad Request
Content-Length: 529
Content-Type: application/json;charset=utf-8
Date: Fri, 22 May 2020 19:58:21 GMT
Server: Jetty(9.4.12.v20180830)

{
    "coercion": "malli",
    "errors": [
        {
            "in": [
                "x"
            ],
            "message": "missing required key",
            "path": [
                1,
                2,
                0
            ],
            "schema": "[:map {:closed true} [:x int?]]",
            "type": "malli.core/missing-key",
            "value": null
        },
        {
            "in": [
                "y"
            ],
            "message": "missing required key",
            "path": [
                2,
                2,
                0
            ],
            "schema": "[:map {:closed true} [:y int?]]",
            "type": "malli.core/missing-key",
            "value": null
        }
    ],
    "humanized": {
        "x": [
            "missing required key"
        ],
        "y": [
            "missing required key"
        ]
    },
    "in": [
        "request",
        "body-params"
    ],
    "schema": "[:or [:map {:closed true} [:x int?]] [:map {:closed true} [:y int?]]]",
    "value": {
        "x": 1
    }
}
@ikitommi
Copy link
Member

ikitommi commented May 24, 2020

Minimal repro:

(m/decode
  [:or
   [:map [:x int?]]
   [:map [:y keyword?]]]
  {:x 1}
  mt/strip-extra-keys-transformer)
; => {}

I think we need to check validity on transformation :leave for each element and pick the first valid one.

@ikitommi
Copy link
Member

should be fixed in [metosin/malli "0.0.1-20200525.162645-15"].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants