Как мне вернуть тело ответа для кольцевого маршрута из выражения (try)?

Я не могу понять, где я ошибаюсь со следующим маршрутом:

(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), чтобы вернуть карту и передать ее обработчику ответа?


person Tyler Collins    schedule 23.05.2017    source источник
comment
не могли бы вы также включить код без try, чтобы увидеть, есть ли еще какое-то различие?   -  person Arthur Ulfeldt    schedule 23.05.2017


Ответы (2)


Трудно догадаться, что могло вызвать пустые ответы при попытке на месте, если только какое-то исключение не возникло по какой-либо другой причине. Возможно, есть разница между тем, что запущено, и тем, что находится в исходном файле, из-за какой-то опечатки или переименованной функции. Следует учитывать, что исключения могут быть выброшены выше по стеку промежуточного программного обеспечения, а также в обработчике.

Если у вас есть это промежуточное программное обеспечение, которое преобразует ответы из структур данных 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})})))))

где вы явно задаете код ответа и смотрите, сможете ли вы понять, что происходит.

person Arthur Ulfeldt    schedule 23.05.2017

Оборачивание всего кода классом 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 - ваш экземпляр исключения.

person Ivan Grishaev    schedule 25.05.2017