Fork me on GitHub
#pedestal
<
2021-11-17
>
simongray08:11:06

So, curiously, even though the documentation kinda lets on that you can reuse negotiate-content for other kinds of negotiation, e.g. language, in practice it is completely hardcoded to content-type. I ended up making my own interceptor and reusing the parsing functions:

(defn ->language-negotiation-ic
  "Make a language negotiation interceptor from a coll of `supported-languages`.

  The interceptor reuses Pedestal's content-negotiation logic, but unlike the
  included content negotiation interceptor this one does not create a 406
  response if no match is found."
  [supported-languages]
  (let [match-fn   (conneg/best-match-fn supported-languages)
        lang-paths [[:request :headers "accept-language"]
                    [:request :headers :accept-language]]]
    {:name  ::negotiate-language
     :enter (fn [ctx]
              (if-let [accept-param (loop [[path & paths] lang-paths]
                                      (if-let [param (get-in ctx path)]
                                        param
                                        (when (not-empty paths)
                                          (recur paths))))]
                (if-let [language (->> (conneg/parse-accept-* accept-param)
                                       (conneg/best-match match-fn))]
                  (assoc-in ctx [:request :accept-language] language)
                  ctx)
                ctx))}))

Fredrik11:11:00

yes, the negotiate-content function itself is hard-coded, but like you've done here, the io.pedestal.content-negotiation has smaller functions you can use to make your own negotiation.