请求映射在 Compojure 处理程序中传递给我的匿名函数
Request map passed to my anonymous function inside a Compojure handler
我花了两天时间学习 Clojure,使用 ring-clojure and Compojure with ring-json 的 wrap-json-body
中间件编写了一个简单的 REST 服务器。
到目前为止,我有:
包含用户(有几个默认用户)的矢量 users
:
(def users [{:id 0 :username "aname"}
{:id 1 :username "anothername"}])
接受地图(用户)并查找具有相同用户名的现有用户的函数(表单?)save-user
。如果用户名可用,我会在 returning HTTP 201 之前覆盖 users
向量以包含新用户。如果用户名被占用,我只需 return HTTP 400:
(defn save-user [user]
(prn users)
(if
(not-any? #(= (:username %) (:username user)) users)
(fn [request]
(def users (conj users user))
(status
(response (str "Saved user with username: " (:username user)))
201))
(status
(response (str "User with username '" (:username user) "' already exists"))
400)))
POST /users
的路线,它使用收到的地图调用 save-user
:
(defroutes app-routes
(POST "/users" request (save-user (:body request))))
我觉得没关系,但是中间件是这样应用的:
(def app
(-> app-routes
(wrap-cors :access-control-allow-origin "*" :access-control-allow-methods "*")
(wrap-json-response)
(wrap-keyword-params)
(wrap-json-body {:keywords? true :bigdecimals? true})
(wrap-defaults (assoc site-defaults :security false))))
我的问题:
无论出于何种原因,整个 request
映射都传递给了我在 if
中作为 then
传递的函数。打印它:
(if
(not-any? #(= (:username %) (:username user)) users)
(fn [request]
(prn request))
...
...给我这个:
{:ssl-client-cert nil, :cookies {}, :remote-addr "0:0:0:0:0:0:0:1", :params {}, :flash nil, :route-params {}, :headers {"host" "localhost:3000", "accept" "*/*", "content-length" "42", "content-type" "application/json", "user-agent" "curl/7.43.0"}, :server-port 3000, :content-length 42, :form-params {}, :compojure/route [:post "/users"], :session/key nil, :query-params {}, :content-type "application/json", :character-encoding nil, :uri "/users", :server-name "localhost", :query-string nil, :body {:username "testusername", :password "testpassword"}, :multipart-params {}, :scheme :http, :request-method :post, :session {}}
如果我将匿名函数作为 if 的 else
传递,也会发生同样的情况。但是,当我只传递 (status ...)
时,没有任何错误发生,就像上面的代码一样。
据我了解,request
映射根本不应该在 save-user
中可用,因为它没有作为参数传递。为什么它传递给了我的匿名函数,有没有办法简单地忽略它?
在 save-user
中,您正在 returning 一个 函数,它接收请求并 return 响应(处理程序)。
我想您应该直接 return 回复。只需将 (fn [request]
替换为 (do
即可将多个表达式包装在一个表单中。
(def users (atom [{:id 0 :username "aname"}
{:id 1 :username "anothername"}]))
(defn save-user [user]
(if (not-any? #(= (:username %) (:username user)) @users)
(do
(swap! users conj user)
(status
(response (str "Saved user with username: " (:username user)))
201))
(status
(response (str "User with username '" (:username user) "' already exists"))
400)))
我还将全局用户变量更改为一个原子。从函数内部重新定义全局变量是 Clojure 中的一大禁忌。
我花了两天时间学习 Clojure,使用 ring-clojure and Compojure with ring-json 的 wrap-json-body
中间件编写了一个简单的 REST 服务器。
到目前为止,我有:
包含用户(有几个默认用户)的矢量 users
:
(def users [{:id 0 :username "aname"}
{:id 1 :username "anothername"}])
接受地图(用户)并查找具有相同用户名的现有用户的函数(表单?)save-user
。如果用户名可用,我会在 returning HTTP 201 之前覆盖 users
向量以包含新用户。如果用户名被占用,我只需 return HTTP 400:
(defn save-user [user]
(prn users)
(if
(not-any? #(= (:username %) (:username user)) users)
(fn [request]
(def users (conj users user))
(status
(response (str "Saved user with username: " (:username user)))
201))
(status
(response (str "User with username '" (:username user) "' already exists"))
400)))
POST /users
的路线,它使用收到的地图调用 save-user
:
(defroutes app-routes
(POST "/users" request (save-user (:body request))))
我觉得没关系,但是中间件是这样应用的:
(def app
(-> app-routes
(wrap-cors :access-control-allow-origin "*" :access-control-allow-methods "*")
(wrap-json-response)
(wrap-keyword-params)
(wrap-json-body {:keywords? true :bigdecimals? true})
(wrap-defaults (assoc site-defaults :security false))))
我的问题:
无论出于何种原因,整个 request
映射都传递给了我在 if
中作为 then
传递的函数。打印它:
(if
(not-any? #(= (:username %) (:username user)) users)
(fn [request]
(prn request))
...
...给我这个:
{:ssl-client-cert nil, :cookies {}, :remote-addr "0:0:0:0:0:0:0:1", :params {}, :flash nil, :route-params {}, :headers {"host" "localhost:3000", "accept" "*/*", "content-length" "42", "content-type" "application/json", "user-agent" "curl/7.43.0"}, :server-port 3000, :content-length 42, :form-params {}, :compojure/route [:post "/users"], :session/key nil, :query-params {}, :content-type "application/json", :character-encoding nil, :uri "/users", :server-name "localhost", :query-string nil, :body {:username "testusername", :password "testpassword"}, :multipart-params {}, :scheme :http, :request-method :post, :session {}}
如果我将匿名函数作为 if 的 else
传递,也会发生同样的情况。但是,当我只传递 (status ...)
时,没有任何错误发生,就像上面的代码一样。
据我了解,request
映射根本不应该在 save-user
中可用,因为它没有作为参数传递。为什么它传递给了我的匿名函数,有没有办法简单地忽略它?
在 save-user
中,您正在 returning 一个 函数,它接收请求并 return 响应(处理程序)。
我想您应该直接 return 回复。只需将 (fn [request]
替换为 (do
即可将多个表达式包装在一个表单中。
(def users (atom [{:id 0 :username "aname"}
{:id 1 :username "anothername"}]))
(defn save-user [user]
(if (not-any? #(= (:username %) (:username user)) @users)
(do
(swap! users conj user)
(status
(response (str "Saved user with username: " (:username user)))
201))
(status
(response (str "User with username '" (:username user) "' already exists"))
400)))
我还将全局用户变量更改为一个原子。从函数内部重新定义全局变量是 Clojure 中的一大禁忌。