Fork me on GitHub
#ring-swagger
<
2021-10-16
>
xiongtx04:10:42

In compojure-api I’m trying to handle the graphql case of treating the body differently based on Content-Type. If the content type is application/json, it’s supposed to be treated as a JSON object. But if it’s application/graphql, then it should be treated as as a plain string. https://graphql.org/learn/serving-over-http/#post-request However, I don’t see an elegant way to do this when defining a schema for the body.

(s/defschema RequestBody
  {:query s/Str
   (s/optional-key :operationName) (s/maybe s/Str)
   (s/optional-key :variables) (s/maybe {s/Keyword s/Any})})

(POST "/" request
  :body [body RequestBody]
  ...)

staypufd14:12:23

I believe you want to use a middleware. From Compojure docs: 1. Middleware Middleware are functions that take a handler as its first argument, and returns a new handler function based on the original. handler & args --> middleware --> handler An example of a simple middleware function is one that adds a header to the output of a handler: (defn with-header [handler header value] (fn [request] (let [response (handler request)] (assoc-in response [:headers header] value)))) To apply this to the existing hello-world handler, you can redefine hello-world with the middleware wrapper. (def hello-world (-> hello-world (with-header "X-Lang" "Clojure") (with-header "X-Framework" "Compojure"))) But a more idiomatic way is to use the decorate macro: (decorate hello-world (with-header "X-Lang" "Clojure") (with-header "X-Framework" "Compojure")) The decorate macro produces the same effect, but retains the original metadata of hello-world. A number of middleware functions are included in Compojure. These augment handlers in various ways. You can wrap a handler in many middleware functions, or none at all. Some of the most commonly used middleware functions are: ◦ with-params ◦ with-cookies ◦ with-multipart ◦ with-session

staypufd14:12:18

So you would check the content-type in the middleware and then it would branch to a different handler for either case, JSON or String. So the schema for the RequestBody would stay the same bc you deal with the headers in a middleware before passing it on to be processed by other middleware and the final handler. The schema your defining is for the RequestBody anyway, and handlers aren't part of a HTTP request body either so I think your schema is fine. The middleware does get the headers and so that seemed to me to be the correct place to check them and call the particular handler for either case. Hope I'm helping and not making it more confusing. 😃