Reputation: 5081
I'm using ring.util.response and for some reason when setting cookies, I'm unable to return a json body from this POST request.
Returning json (dictionary) in the line below results in the error below. Whereas returning a plaintext string response works fine.
Does anyone know what I'm doing wrong?
I'm able to return json payloads fine from other GET routes.
(ns tool.session
(:require
[tool.config :refer [env]]
[clj-http.client :as client]
[clojure.tools.cli :refer [parse-opts]]
[clojure.tools.logging :as log]
[clojure.string :as s]
[cheshire.core :refer :all]
[slingshot.slingshot :refer [try+, throw+]]
[ring.util.codec]
[ring.util.response :refer [response]]
[mount.core :as mount])
)
;; Functions for user web session related access
(defn set-session-user! [business-external-id data-preferences-uuid {session :session}]
(-> (response (str "Business id set to: " business-external-id) )
;; (-> (response {} ) ;; PUTTING this line results in the error below. Whereas returning a plaintext string response works fine.
(assoc :session (assoc session :business_external_id business-external-id))
(assoc :session (assoc session :data_preferences_uuid data-preferences-uuid))
(assoc :headers {"Content-Type" "text/plain"})))
The error I get is
2022-09-21 00:51:21,838 [XNIO-1 task-2] ERROR io.undertow.request - UT005071: Undertow request failed HttpServerExchange{ POST /login/session-post}
java.lang.UnsupportedOperationException: Body class not supported: class clojure.lang.PersistentArrayMap
at ring.adapter.undertow.response$eval20252$fn__20253.invoke(response.clj:46)
at ring.adapter.undertow.response$eval20207$fn__20208$G__20198__20215.invoke(response.clj:11)
at ring.adapter.undertow.response$set_exchange_response.invokeStatic(response.clj:59)
at ring.adapter.undertow.response$set_exchange_response.invoke(response.clj:52)
at ring.adapter.undertow$handle_request.invokeStatic(undertow.clj:23)
at ring.adapter.undertow$handle_request.invoke(undertow.clj:19)
at ring.adapter.undertow$undertow_handler$fn$reify__20336.handleRequest(undertow.clj:41)
at io.undertow.server.session.SessionAttachmentHandler.handleRequest(SessionAttachmentHandler.java:68)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449)
at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
at java.base/java.lang.Thread.run(Thread.java:833)
For more context, that code is called from my main route
(defn log-in-to-business [{:keys [body-params] :as req}]
(def business-uuid (:business_uuid body-params))
(def data-preferences-uuid (:data_preferences_uuid body-params))
(session/set-session-user! business-uuid data-preferences-uuid req)
)
Upvotes: 1
Views: 289
Reputation: 7568
I guess that :body
of the request has to be a string, so you have to convert your hash-map representing JSON payload with some library (data.json or cheshire):
(cheshire.core/encode {})
=> "{}"
And then pass this result into ring.util.response/response
.
Some notes about your code:
In set-session-user!
, you change :session
of response to (assoc session :business_external_id business-external-id)
.
Then you overwrite this value to (assoc session :data_preferences_uuid data-preferences-uuid)
, losing :business_external_id
from the previous step.
I think you should use merge
or something like that:
(defn set-session-user! [business-external-id data-preferences-uuid {session :session}]
(-> (response (str "Business id set to: " business-external-id))
(assoc :session (merge session {:business_external_id business-external-id
:data_preferences_uuid data-preferences-uuid}))
(assoc :headers {"Content-Type" "text/plain"})))
And in log-in-to-business
, unless you really need to create global variables, you should use let
instead (which creates local variables):
(defn log-in-to-business [{:keys [body-params] :as req}]
(let [business-uuid (:business_uuid body-params)
data-preferences-uuid (:data_preferences_uuid body-params)]
(session/set-session-user! business-uuid data-preferences-uuid req)))
Upvotes: 2