如何在 Lucerne 中捕获解析错误(常见的 lisp)

How to catch parse errors in Lucerne (common lisp)

我正在尝试在 Lucerne 构建一个简单的 rest api,但是如果 json 格式错误,clack:call 方法将失败。所以,我扩展了 bass-app class 并添加了一个 around 方法:

(defclass tracker-app (base-app) ()
  (:documentation "An extension of lucerne's base app to control behavior"))

(defmethod clack:call :around ((app tracker-app) env)
  (handler-case (call-next-method)

    (fast-http:cb-message-complete (e)
      (vom:error "could not build message body: ~a" e)
      (respond nil :status 400))

    (:no-error (res) res))) 

(defapp server :class 'tracker-app)

(start server :server woo)

但是解析错误继续导致服务器崩溃。

我对 clos 了解不多,所以我担心我误解了如何在这种情况下捕获错误。

编辑:添加了启动信息

编辑:添加堆栈跟踪

[这个答案是错误的: fast-http.error:cb-message-complete & fast-http:cb-message-complete 似乎是同一个符号。为了后代,我把它留在这里。]

您没有处理正确的情况(事实上,我不确定您是否正在处理一个根本存在的情况,我希望系统可能已经发出警告,尽管也许它可以' t).

您需要处理 fast-http.error:cb-message-complete,但您的处理程序指定 fast-http:cb-message-complete。其中第一个是条件(定义here, while the second is I think implicitly define here并且不是条件而是我认为的函数名称。

一个更通用的技巧是尝试处理一些过于通用的错误:您可能最终会处理一些您不知道如何处理的事情,但是如果您的处理程序被调用,您就知道调用堆栈看起来像您认为在发出错误信号时会发生。然后你就可以开始处理你真正关心的错误了。在这种情况下,我认为这可能意味着 fast-http.error:callback-error

假设*features*不包含:catch-any-error,这里是一个完整的测试用例:

(ql:quickload :lucerne)
(defpackage :so.lucerne (:use :cl :lucerne))
(in-package :so.lucerne)

(defclass tracker-app (base-app) ()
  (:documentation "An extension of lucerne's base app to control behavior"))

(defmethod clack:call :around ((app tracker-app) env)
  (handler-case (call-next-method)
    (fast-http:cb-message-complete (e)
      (warn "could not build message body: ~a" e)
      (respond nil :status 400))
    #+catch-any-error
    (error (e) (break "BREAK with ~a" e))
    (:no-error (res) res))) 

(defmethod clack:call ((app tracker-app) env)
  (error "Oh No"))

(defapp server :class 'tracker-app)
(start server :server :woo)

当我尝试加载 localhost:8000 时,显示以下错误:

Callback Error: the message-complete callback failed
  Oh No
   [Condition of type FAST-HTTP.ERROR:CB-MESSAGE-COMPLETE]

[Condition of type FAST-HTTP.ERROR:CB-MESSAGE-COMPLETE] 上按 Enter 得到:

#<FAST-HTTP.ERROR:CB-MESSAGE-COMPLETE {10048315C3}>
--------------------
The object is a CONDITION of type FAST-HTTP.ERROR:CB-MESSAGE-COMPLETE.
FORMAT-CONTROL: NIL
FORMAT-ARGUMENTS: NIL
DESCRIPTION: "the message-complete callback failed"
ERROR: #<SIMPLE-ERROR "Oh No" {1004831583}>

错误包含另一个错误。

现在如果我(push :catch-any-error *features*)重新编译上面的方法,同样的测试使代码到达(break ...)语句,显示为BREAK with Oh No.

说明

没有 fast-http:cb-message-complete 被捕获,实际上此时没有发出这样的信号;相反,在这个位置,我们只能捕获发出信号的特定错误。只有 在调用堆栈 的更高层,错误才包含在 fast-http:cb-message-complete 个错误中。

解决方案

在你的情况下,你可以直接捕获 jonathan.error:<jonathan-error>(不寻常的命名约定,但没关系),jonathan 库中所有错误的基础 class(你可以捕获特定的错误类型,但你可能会遗漏一些其他情况)。