I'm trying to get my ClojureScript frontend to communicate with my Clojure backend. Here's the frontend code:

(ns ^:figwheel-hooks simple-server.core
  (:require [clojure.string :as str]
            [ajax.core :refer [GET POST]]
            [goog.dom :as gdom]
            [goog.events :as events]
            [reagent.core :as r :refer [atom]]
            [reagent.dom :as rdom]
            [reitit.core :as reitit]
            [cljs.core.async :as a
             :refer [>! <! go chan buffer close! alts! timeout]]
            [cljs-http.client :as http]))
(def site-url "http://localhost:9500")

;; guesser page stuff
(def guess-val      (r/atom 5))

(def guess-text "Guess the number I'm thinking of!")
(defonce app-state (r/atom {:text guess-text}))


(defn slider-on-change-handler [js-event]
  (reset! guess-val (-> js-event .-target .-value)))

(defn multiply [a b] (* a b))


;; login page functions
(defn form-sanitizer [input]
  (str/lower-case (str/trim input)))


;; Channels, async, other considerations
(defn get-app-element []
  (gdom/getElement "app"))

(defonce event-channel (chan 10))

(defn dispatch-event! [e]
  (case (:type e)
    :login-success  (swap! app-state merge
                           {:user-authenticated true
                            :message "Login successful, start guessing!"})
    :login-fail     (swap! app-state assoc :message "Login failed! Try again.")
    :guess-response (swap! app-state assoc :message (str "Server says: " (:message e)))
    :guess-error    (swap! app-state assoc :message "Error submitting guess.")
    (println "Unknown event type: " e)))

(defonce global-handler
  (go
    (while true
      (let [e (<! event-channel)]
        (dispatch-event! e)))))


;; Frontend event handler to update username and password
(defn update-credentials [field value]
  (swap! app-state assoc field value))


;; Frontend event handler to submit the login form
(defn submit-login []
  (let [{:keys [username password]} @app-state]
    ;; (println "keys are" username "and" password)
    (go
      (let [response (<! (http/post (str site-url "/api/login")
                                    {:json-params {:username (form-sanitizer username) :password password}}))]
        ;; (def r response)
        ;; (println response)
        
        #_(if (:success response)
          (>! event-channel {:type :login-success})
          (>! event-channel {:type :login-fail}))))))

;; Frontend event handler to submit guesses to the backend
(defn submit-guess []
  (let [guess (@app-state :guess)]
    (go
      (let [response (<! (http/post (str site-url "/api/guess")
                                    {:json-params {:guess guess}}))]
        (if (:success response)
          (>! event-channel {:type :guess-response :message (:body response)})
          (>! event-channel {:type :guess-error}))))))


;; Login component
(defn login-page []
  [:div.login-form
   [:h1 "Login"]
   [:input {:type "text"
            :placeholder "Username"
            :on-change #(update-credentials :username (-> % .-target .-value))}]
   [:input {:type "password"
            :placeholder "Password"
            :on-change #(update-credentials :password (-> % .-target .-value))}]
   [:button {:on-click submit-login} "Login"]
   [:div.message (@app-state :message)]
   [:h3  (str @app-state)]])




(defn guessing-page []
  [:div.guessing-game
   [:h3 "Guess the number I'm thinking of!"]
   [:input {:type "number"
            :value (@app-state :guess)
            :on-change #(swap! app-state assoc :guess (-> % .-target .-value))}]
   [:button {:on-click submit-guess} "Submit Guess"]
   [:div.message (@app-state :message)]])


(defn guess-page []
  [:div
   [:h1 "Guessing Game"]
   [:h3 (:text @app-state)]
   [:div {:class "slidecontainer"}
    [:input {:type  "range"
             :id    "MyRange1"
             :min   1
             :max   10
             :value 5
             :on-change slider-on-change-handler}]]
   [:button {:on-click submit-guess} "Submit Guess!"][:h3 @guess-val]])

;; Conditional rendering based on authentication
(defn app-root []
  (if (@app-state :user-authenticated)
    [guess-page]
    [login-page])
)

(defn mount-app []
  (rdom/render [app-root] (.getElementById js/document "app")))

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(defn ^:after-load on-reload []
  ;; Re-mount the app after code reloading occurs
  (mount-app))

;; Initial mounting of the app
(mount-app)


Here's the backend code:

(ns simple-server.server
  (:require 
   [clojure.string :as str]
   [compojure.coercions   :refer [as-int]]
   [compojure.core        :refer [ANY defroutes GET POST OPTIONS]]
   [compojure.route           :as route]
   [ring.adapter.jetty    :refer [run-jetty]]
   [ring.middleware.defaults  :as middleware]
   [ring.middleware.json :refer [wrap-json-response]]
   [ring.middleware.cookies   :as cookies]
   [ring.middleware.multipart-params :as multi]
  ;;  [ring.middleware.cors :refer [wrap-cors]]
   [ring.mock.request         :as mock]
   [ring.util.response        :as ring
    :refer [not-found redirect response status]]
   [simple-server.simple-game :as game]
   [simple-server.db          :as db]
   [byte-transforms           :as transforms]
   [clojure.pprint :as pprint]))

;; (defn random-api []
;;   (println "I've been called!")
;;   {:status 200
;;    :body (pr-str {:lucky-number (rand-int 1000)
;;                   :a-set #{1 "foo" :baz [::a ::b]}})
;;    :headers {"Content-Type" "application/edn"}})

(defn set-session-cookie [response user-id]
  (let [cookie-value (transforms/hash (str user-id) :crc32)] ; Generate a simple cookie value based on the user ID
    (ring/set-cookie response "token" cookie-value {:max-age 3600}))) ; Set cookie with a maximum age of 1 hour

(defn get-session-cookie [request]
  (get-in request [:cookies "token" :value]))


(defn new-game-handler [request]
  (when (game/new-game! (get-session-cookie request))
    (response (str "OK - start guessing at /guess/?guess=N"))))


(defn valid-login? [token password] ;; placeholder login logic...
  (or (and (= token "foo") (= password "bar"))
      (and (= token "admin") (= password "123"))
      (and (= token "user") (= password "pass"))
      (and (= token "egg") (= password "man"))
      (and (= token "test") (= password "test"))))

;; ;; tried to combine these functions but the login page is very fragile
;; (defn login-page-handler []
;;   (response (slurp "resources/public/login.html")))
;; ;; (defn guess-page-handler []
;; ;;   (response (slurp "res/guess.html")))


(defn validate-user-credentials [username password]
  (let [user-id-map (first (db/get-user-id username)) 
        user-id (:user_id user-id-map)                 
        password-map (first (db/get-password user-id))
        stored-password (:password password-map)]
    (= password stored-password)))

(defn random-api []
  (println "I've been called!")
  {:status 200
   :body (pr-str {:lucky-number (rand-int 1000)
                  :a-set #{1 "foo" :baz [::a ::b]}})
   :headers {"Content-Type" "application/edn"}})

(defn login-api-handler [request]
  (println request)
  (let [params (get request :params)
        username (:username params)
        password (:password params)]
  (println "got params:" username password)
    (if (validate-user-credentials username password)
      (let [user-id (-> (first (db/get-user-id username))
                        :user_id)]
        (response {:status "success", :message "Login successful222"})
        #_(-> (response {:status "success", :message "Login successful"})
            #_(set-session-cookie user-id)))
      (response {:status "error", :message "Invalid login. Try again."}))))

(defn guess-api-handler [request]
  (let [params (get request :params)
        guess (Integer/parseInt (:guess params))
        token (get-session-cookie request)]
    (if (nil? token)
      (response {:status "error", :message "Unauthorized"})
      (let [result (game/guess-answer guess token)]
        (response {:status "success", :message (name result), :tries-left (db/get-remaining-tries token)})))))

(defn guess-handler [guess user-hash]
  (condp = (game/guess-answer guess user-hash)
    nil       (-> (response  "You need to supply a guess with /guess?guess=N")
                  (status 400))
    :game-win  (response  (str "Congratulations! You win!"))
    :game-over (response  "Too bad! You ran out of tries!")
    :too-low   (response  (str "Too low! "  (db/get-remaining-tries user-hash) " tries remaining!"))
    :too-high  (response  (str "Too high! " (db/get-remaining-tries user-hash) " tries remaining!"))))



(defroutes site-routes

  ;; (GET  "/login"             []                          (login-page-handler))
  ;; (POST "/login"             request                     (login-handler request))
  (POST "/api/login"         request                     (login-api-handler request))
  (POST "/api/guess"         request                     (guess-api-handler request)) 
  (POST  "/api/random"        []                          (random-api))
  
  ;; (OPTIONS "*"               []                          {}) ;; handle preflight requests
 
  ;; (OPTIONS "*" [] (fn [request]
  ;;                   (-> (response "")
  ;;                       (ring/header "Access-Control-Allow-Origin" "http://localhost:9500")
  ;;                       (ring/header "Access-Control-Allow-Methods" "POST, GET, OPTIONS")
  ;;                       (ring/header "Access-Control-Allow-Headers", "content-type, x-requested-with")
  ;;                       (ring/header "Access-Control-Allow-Credentials", "true"))))

  (GET  "/new-game"          request                     (new-game-handler request))
  ;; (GET  "/guess:token"    [token]                     (guess-page-handler token))
  (GET  "/guess"             [guess :<< as-int :as request]  (guess-handler guess (get-session-cookie request)))
  (ANY  "*"                  []                          (not-found (str "Sorryasd, noz such URI on this server!"))))

(defn add-content-type-htmltext-header [handler]
  (fn [request]
    (let [response (handler request)]
      (-> response
          (ring/header "Content-Type" "application/json")))))


;; (defn redirect-to-login-middleware
;;   "If a login cookie (at present, can be anything) is not found, redirects user to the login page."
;;   [handler]
;;   (println "ASDSADASDSADAS")
;;   (fn [request]
;;     (let [token (get-session-cookie request)]
;;       ;(clojure.pprint/pprint request)
;;       (if (nil? token)
;;         (-> (handler (assoc request :uri "/login"))  ; Redirect to /login
;;             (ring/header "Content-Type" "text/html"))
;;         (handler request)))))


(def handler
  (-> site-routes
      ;; (wrap-cors :access-control-allow-origin ["http://localhost:9500"] ;; replace with your frontend domain/URL
      ;;            :access-control-allow-credentials true
      ;;            :access-control-allow-methods [:get :post :put :delete :options]
      ;;            :access-control-allow-headers ["Content-Type" "Authorization"]
      ;;            :access-control-max-age 3600)
      (middleware/wrap-defaults middleware/api-defaults)
      ;; (redirect-to-login-middleware)
      (add-content-type-htmltext-header)

      (multi/wrap-multipart-params)
      (wrap-json-response)
      (cookies/wrap-cookies)))


(comment
  (handler (mock/request :get "/new-game"))
  (handler (mock/request :get "/guess?guess=3"))
  (handler (mock/request :get "/dunno")))

;; #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
;; (defonce server
;;   (future (run-jetty #'handler {:port 9500 :join? false})))



The problem is that the username and password don't seem to be being sent in the response. The backend receives this:
{:ssl-client-cert nil, :protocol HTTP/1.1, :cookies {pga4_session {:value fadbd9dd-6290-40b4-bf50-3f8d426020ed!vWgG8Nn3PIgKJKY63RFrVTBs4ILsMZsJRGFnWO1JcDA=}, PGADMIN_LANGUAGE {:value en}}, :remote-addr 127.0.0.1, :params {}, :flash nil, :route-params {}, :headers {origin http://localhost:9500, sec-fetch-site same-origin, host localhost:9500, user-agent Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0, content-type application/json, cookie pga4_session=fadbd9dd-6290-40b4-bf50-3f8d426020ed!vWgG8Nn3PIgKJKY63RFrVTBs4ILsMZsJRGFnWO1JcDA=; PGADMIN_LANGUAGE=en, content-length 35, referer http://localhost:9500/, connection keep-alive, accept */*, accept-language en-US,en;q=0.5, sec-fetch-dest empty, accept-encoding gzip, deflate, br, sec-fetch-mode cors, dnt 1, sec-gpc 1}, :server-port 9500, :content-length 35, :form-params {}, :compojure/route [:post /api/login], :session/key nil, :query-params {}, :content-type application/json, :character-encoding UTF-8, :uri /api/login, :server-name localhost, :query-string nil, :body #object[org.eclipse.jetty.server.HttpInputOverHTTP 0x53cc0360 HttpInputOverHTTP@53cc0360[c=0,q=0,[0]=null,s=STREAM]], :multipart-params {}, :scheme :http, :request-method :post, :session {}}

But I don't see the username and password being sent over.