【问题标题】:How to catch parse errors in Lucerne (common lisp)如何在 Lucerne 中捕获解析错误(常见的 lisp)
【发布时间】:2019-12-31 21:23:40
【问题描述】:

我正在尝试在 Lucerne 构建一个简单的 rest api,但如果 json 格式错误,clack:call 方法会失败。所以,我扩展了 bass-app 类并添加了一个 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 了解不多,所以我担心我误解了如何在这种情况下捕获错误。

编辑:添加开始信息

编辑:添加堆栈跟踪

【问题讨论】:

  • 我认为需要更多细节。你如何构建你的应用程序(哪些中间件),你的处理程序是什么?
  • 谢谢,我已经添加了这些信息。为了简单起见,我现在没有使用中间件(可以用来解决这个问题)并且服务器很糟糕。问题发生在路线调度之前,所以我将其排除在外。
  • 我不知道clack:call 在哪里发挥作用,我懒得尝试。据我记得,woo 使用异步请求处理。因此,您的错误可能发生在不同的线程中。您是否尝试过其他服务器?
  • 我检查了 Lucernes 基础应用程序和我的扩展和 clack:call 的错误堆栈
  • 希望对您有所帮助。我看到两个 clack 调用,所以我真的很困惑为什么我的错误处理不起作用

标签: json rest parsing common-lisp clos


【解决方案1】:

假设*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:&lt;jonathan-error&gt;(不寻常的命名约定,但可以),jonathan 库中所有错误的基类(您可以捕获特定的错误类型,但您可能会错过其他一些错误例)。

【讨论】:

  • 就是这样。非常感谢。这让我发疯了
【解决方案2】:

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

您没有处理正确的条件(事实上,我不确定您是否正在处理一个根本存在的条件,我希望系统可能已经警告过,尽管它可能不能) .

您需要处理fast-http.error:cb-message-complete,但您的处理程序指定fast-http:cb-message-complete。其中第一个是条件(定义here,而第二个是我认为隐含定义here,不是条件而是我认为的函数名称。

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

【讨论】:

  • 我已经尝试了这两种方法。如果您查看here,您会看到fast-http.error 的内容已导入,以便可以导出here。不过,感谢有关技巧的段落。如果我也能做到这一点,那可能是构建它的更好方法。
  • @pricks:哦,我没有意识到它们是同一个符号:我没有很好地阅读 fast-http 的包定义。抱歉我之前(现已删除)的尖刻评论。
猜你喜欢
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 2023-03-13
  • 2019-02-05
相关资源
最近更新 更多