2

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?

Agent 008
  • 141
  • 8
  • 1
    this looks like coercion to HTML produced key-value pairs of the request map (i.e. like iterating over a map) – Jochen Bedersdorfer Mar 23 '20 at 02:19
  • @JochenBedersdorfer so maps get turned into a set of key-value pairs in the response, which means that it's just a nested map? – Agent 008 Mar 23 '20 at 03:00
  • 1
    yeah, that's the beauty of ring. Request is just a map. And depending on your ring configuration, the map will be converted to a JSON payload or whatever you like. Apparently by default it is treated as a seq. (see the various wrap- fns for more info) – Jochen Bedersdorfer Mar 23 '20 at 04:38
  • Try to pass a string as `:body`, for example `:body (clojure.pprint/pprint request)`. Also, set the content type to `text/plain`. I can imagine that this removes some magic that's currently confusing you. – Stefan Kamphausen Mar 23 '20 at 20:44

0 Answers0