Clojure 如何从(try)表达式中返回环形路由的响应体?

Clojure 如何从(try)表达式中返回环形路由的响应体?,clojure,compojure,ring,Clojure,Compojure,Ring,我不知道以下路线哪里出了问题: (ns mds.routes.api (:require [mds.db.core :refer [*db*] :as db] [compojure.core :refer [defroutes POST]] [ring.util.http-response :as response] [clojure.walk :as walk])) (defroutes api-routes (P

我不知道以下路线哪里出了问题:

(ns mds.routes.api
 (:require [mds.db.core :refer [*db*] :as db]
            [compojure.core :refer [defroutes POST]]
            [ring.util.http-response :as response]
            [clojure.walk :as walk]))

(defroutes api-routes
  (POST "/student" request
       (let [{body :body} request]
         (let [student (walk/keywordize-keys body)]
           (try
             (db/create-student! student)
             {:saved true
              :error nil
              :student student}
             (catch Exception e  {:saved false
                                    :error e
                                    :student nil})
             )))))
我试图返回一个带有json对象的响应体,该对象类似于:

{
    "saved":"true",
    "error":"nil",
    "student": {...}
}
但我只是得到了空洞的回应。
db/create student调用工作正常,不使用(try)表达式,我会得到JSON正文或500错误,但使用(try)表达式,我每次都会得到一个空的status 200响应


如何获取(try)表达式以返回映射并将其传递给响应处理程序?

很难猜测try处于适当位置时会导致空响应的原因,除非由于其他原因引发异常。可能由于某些输入错误或重命名的函数,正在运行的内容与源文件中的内容之间存在差异。需要考虑的是,异常可以在中间件堆栈中以及处理程序中进一步抛出。p> 如果将此包在中间件中,将响应从clojure数据结构(.edn)转换为json,则该中间件可能会抛出异常,试图序列化异常。在这种情况下,
e
。尝试以下测试:

(defroutes api-routes
  (POST "/student" request
        (let [{body :body} request
              student (walk/keywordize-keys body)]
          (try
            (db/create-student! student)
            {:saved true
             :error nil
             :student student}
            (catch Exception e {:saved false
                                :error (.getMessage e)
                                :student nil})))))
并检查输出/logs/nrepl缓冲区中是否存在关于在catch表达式中生成响应时引发异常的异常

如果您在其他地方没有任何json响应,请尝试以下方法:

(defroutes api-routes
  (POST "/student" request
        (let [{body :body} request
              student (walk/keywordize-keys body)]
          (try
            (db/create-student! student)

            {:status 200
             :body (str {:saved true
                         :error nil
                         :student student})}
            (catch Exception e {:status 401
                                :body (str {:saved false
                                            :error (.getMessage e)
                                            :student nil})})))))

在这里,您可以显式设置响应代码,并查看是否可以了解发生了什么。

使用
异常包装整个代码
将其归类为错误做法,因为它的大小写太宽。它可以防止您看到真正重要的错误,例如丢失文件、错误配置、无效参数和其他体系结构错误

但是,如果确实需要捕获所有异常,至少可以打印或返回堆栈跟踪以查看发生了什么:

(ns foo
  (require [clojure.stacktrace :as trace]))

...

;; your handler goes here
(let [trace-string (with-out-str
                     (trace/print-throwable e))]
  {:status 500
   :body trace-string})

其中
e
是您的异常实例。

您是否可以在不使用
的情况下包含代码,并尝试
以查看是否存在其他差异?