如何在 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(你可以捕获特定的错误类型,但你可能会遗漏一些其他情况)。
我正在尝试在 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(你可以捕获特定的错误类型,但你可能会遗漏一些其他情况)。