【问题标题】:How do I return a response body for a ring route from within a (try) expression?如何从 (try) 表达式中返回环路由的响应正文?
【发布时间】:2017-10-22 18:20:15
【问题描述】:

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

(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) 表达式我每次都得到一个空的状态 200 响应。

如何让 (try) 表达式返回地图并将其传递给响应处理程序?

【问题讨论】:

  • 能不能把不带try的代码也加进去看看有没有其他区别?

标签: clojure compojure ring


【解决方案1】:

除非由于某些其他原因引发了一些异常,否则很难猜测是什么导致了 try 的空响应。由于某些拼写错误或重命名的函数,运行的内容和源文件中的内容可能存在差异。需要考虑的一件事是异常可以在中间件堆栈以及处理程序中进一步抛出。

如果您将其封装在中间件中,该中间件将响应从 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})))))

并检查 output/logs/nrepl-buffer 中有关在 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})})))))

你在哪里明确设置响应代码,看看你是否能弄清楚发生了什么。

【讨论】:

    【解决方案2】:

    Exception 类包裹整个代码是不好的做法,因为它的大小写太宽了。它可以防止您看到真正重要的错误,例如丢失文件、错误配置、无效参数和其他架构错误。

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

    (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 是您的异常实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 2015-10-21
      • 2012-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多