This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-10-16
Channels
- # announcements (16)
- # asami (5)
- # aws (2)
- # babashka (4)
- # beginners (22)
- # calva (28)
- # cider (3)
- # clj-kondo (1)
- # cljdoc (13)
- # cljs-dev (16)
- # clojure (3)
- # clojure-australia (1)
- # clojure-europe (25)
- # clojure-gamedev (1)
- # clojure-germany (2)
- # fulcro (34)
- # helix (4)
- # jobs-discuss (16)
- # leiningen (10)
- # malli (20)
- # meander (7)
- # nrepl (35)
- # off-topic (1)
- # portal (13)
- # ring-swagger (3)
- # shadow-cljs (34)
- # tools-deps (7)
- # vim (1)
In compojure-api
I’m trying to handle the 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]
...)
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
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. 😃