How exactly are POST request bodies processed in Clojure? (http-kit, compojure)

1k Views Asked by At

I have a page with a login form, and a server that accepts POST requests. Here is the server:

(ns clj_server.core
  (:require [org.httpkit.server :refer [run-server]]
            [compojure.core :refer [defroutes POST]]
            [compojure.route :as route]
            [ring.middleware.params :refer [wrap-params]]))

(defn printPostBody [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body request})

(defroutes routes
  (POST "/login" request (printPostBody request))
  (route/not-found {:status 404 :body "<h1>Page not found</h1"}))

(def app (wrap-params routes))

(defn -main [& args]
  (run-server app {:port 8000})
  (println "Server started on port 8000"))

When I make a login request, this is printed out:

[:remote-addr "0:0:0:0:0:0:0:1"][:params {"username" "asdf", "password" "ghkj"}][:route-params {}][:headers {"origin" "http://localhost:3449", "host" "localhost:8000", "user-agent" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.172 Safari/537.36 Vivaldi/2.5.1525.46", "content-type" "application/x-www-form-urlencoded", "content-length" "27", "referer" "http://localhost:3449/", "connection" "keep-alive", "upgrade-insecure-requests" "1", "accept" "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3", "accept-language" "en-US,en;q=0.9", "accept-encoding" "gzip, deflate, br", "cache-control" "max-age=0"}][:async-channel #object[org.httpkit.server.AsyncChannel 0x2212125a "/0:0:0:0:0:0:0:1:8000<->/0:0:0:0:0:0:0:1:50592"]][:server-port 8000][:content-length 27][:form-params {"username" "asdf", "password" "ghkj"}][:compojure/route [:post "/login"]][:websocket? false][:query-params {}][:content-type "application/x-www-form-urlencoded"][:character-encoding "utf8"][:uri "/login"][:server-name "localhost"][:query-string nil][:body #object[org.httpkit.BytesInputStream 0x4e67c6c0 "BytesInputStream[len=27]"]][:scheme :http][:request-method :post]

So I'm wondering, what kind of data structure is it? It doesn't look like a hash map, yet when I print out (:params request) instead of request, I get

["username" "asdf"]["password" "ghkj"]

Is it a hash-map of a list of vectors? I don't understand what kind of data structure I'm dealing with here.

Also, why is {"username" "asdf", "password" "ghkj"} being converted into ["username" "asdf"]["password" "ghkj"] when I only ask for the params instead of the whole request?

I then tried printing out (get (:params request) "username") and I got "asdf". Which makes sense, but how is it allowing me to use get on a collection of multiple vectors?

Finally, how would I process JSON in my post requests? Is it just the same thing, or would I have to handle it differently?

0

There are 0 best solutions below