1

I have a route for which I have to get all of parameters from body. I have no choice because it will be called from a third party system so I have to work with simple tools. I also don't have complete control of the data that is passed and I need everything anyway. I need every field but I don't know what those are.

One of the solutions would be to cherry-pick all fields that can be submitted and use optional parameters, but that's not ideal because I'll have to test that by hand for all request types.

And as I figured out there are at least 30 different submitted fields in my request which are needed to be concatenated for HMAC request validation. You can guess how my handler looks like... (Hint: {Field :- s/Str ""}) And I have one more request that is going to be at least this big but different. And I plan more in the future. Oof.

So: How do I get all of the submitted body parameters without any deserialization? HTTP Body string, parameter map or InputStream are completely acceptable solutions. At this point anything is better than specifying all of that by hand. (VIM macros -- thanks for all your help)

My code:

(ns api.compojure-api
  (:require [compojure.api.sweet :refer :all]
            [schema.core :as s]
            [ring.util.http-response :refer :all]
            [ring.middleware.params]
            [muuntaja.middleware]))
(def app
  (api
   (context "/something" []

(POST "/api/:variable" req
       :middleware [;;ring.middleware.params/wrap-params ;; This does nothing
                    ;;muuntaja.middleware/wrap-params ;; This does nothing
                    (fn [handler]
                      (fn
                        ([request]
                         (println "request" request) ;; This prints the request but params are not there, they are not deserialized
                         (handler request))
                        ([request respond raise]
                         (println "request" request)
                         (handler request respond raise))))]
       ;; :body-params [some-body-param :- s/Str] ;; This works if I know the fields. But I don't want to know or specify.
       ;; :coercion nil ;; stops coercing the output, but I need to not coerce the input into String or Object too.

       (println (:params req)) ;; this prints only value from path (`:variable`), but not from body.
       (ok))

)))

I've tried multiple things but nothing worked so far.

I can't copy the methods from compojure examples that wrap whole routes because compojure.api.sweet is different from plain compojure.

Versions:

[org.clojure/clojure "1.10.1"]
[metosin/compojure-api "1.1.13"]
[ring/ring-core "1.8.0"]
[metosin/muuntaja "0.6.6"]
[metosin/ring-http-response "0.9.1"]

All of these solutions return nil: How to get all the params of a POST request with Compojure

muuntaja.middleware/wrap-format middleware (and together with wrap-params in both orders) also doesn't do anything.

I also tried to print (slurp (:body req)) and ring.util.request/body-string but it's empty. In fact this is the output of (println (:body req)):

#object[org.eclipse.jetty.server.HttpInputOverHTTP 0x12335807 HttpInputOverHTTP@12335807[c=0,q=0,[0]=null,s=EOF]]

Which says that parameter s=EOF. But I've set the content type to form and added some data to the body.

vvwccgz4lh
  • 86
  • 9

0 Answers0