我有一个带有多个REST API的scalatra servlet。出于日志记录的目的,我使用after()方法在调用每个API后打印出返回状态代码。
after() {
logger.info("request {} {} returned with status code {}", request.getMethod, request.getRequestURL, response.getStatus.toString)
}
我注意到当方法返回halt
时,状态代码会正确打印,但是当方法返回最后一行的状态代码(没有halt
)时,状态代码是无论实际状态如何,将被打印的总是200。
例如:
post("/users/:user") {
try {
//some logic here...
if(condition)
halt(InternalServerError("DB error")) //this will cause status 500 to be printed in the 'after' method
} catch {
case e: Exception =>
InternalServerError("an unknown error occurred") //this will cause status 200 to be printed in the 'after' method
}
}
用户在两种情况下都会获得真实的状态代码(500)。
知道为什么会这样吗?这是一个错误吗? 我在scalatra-user邮件列表上发布了这个问题,但列表似乎非常不活跃。
阿里扎
答案 0 :(得分:1)
(免责声明:我不是Scalatra开发人员,但我一直在将它用于项目。这是基于我不久前阅读代码。)
这与Scalatra处理抛出异常的方式有关(相关代码似乎从this one开始)。如果抛出runActions
异常的某个地方(halt
抛出HaltException
),catch
cradleHalt
块将会被调用,我们会转到{{ 1}}将设置响应状态代码。
如果您未调用renderHaltException
但直接返回halt
,则情况并不完全相同。在这种情况下,ActionResult
似乎会产生一个值,然后传递给executeRoutes
,然后调用renderResponse
,最后调用renderResponseBody
。 This block似乎是实际设置renderPipeline
的实际状态代码的地方。但是,ActionResult
函数已被调用(它在after
中调用,在actionResult
返回之前)。所以你得到的正是你的行为:当你不使用executeRoutes
时,正确的响应状态只在实际响应中设置,而不是在你的记录调用中设置。
您可能已经尝试过此操作,但是halt
在记录时未生成正确的HTTP状态代码的快速修复只是将其包含在另一个InternalServerError
调用中。
至于这是否是一个bug,我不能说。我猜可能不是,因为他们确实在halt
文档中说executeRoutes
在after
传递给actionResult
之前被调用。不清楚的是,呈现renderResponse
的行为还设置了您想要记录的HTTP错误代码。
你必须与他们确认:)。