2016-03-03 24 views
0

我有一個帶有多個REST API的scalatra servlet。爲了記錄目的,我使用after()方法在每個API被調用後打印出返回狀態碼。Scalatra:打印所有API的HTTP狀態代碼

after() { 
    logger.info("request {} {} returned with status code {}", request.getMethod, request.getRequestURL, response.getStatus.toString) 
} 

我已經注意到,當一個方法與halt返回時,狀態碼被正確地打印,但是,當該方法在最後一行返回狀態碼(不halt),其將被打印的狀態代碼將無論返回的實際狀態如何,始終爲200。

例如:

post("https://stackoverflow.com/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郵件列表上發佈了這個問題,但是這個列表似乎很不活躍。

阿里扎

回答

1

(免責聲明:我不是一個Scalatra的開發者,但我一直在使用它的一個項目是這是基於我閱讀代碼前一段時間)。

這必須做用Scalatra處理拋出異常的方式(相關代碼似乎從this one開始)。如果在runActions的某個地方拋出異常(halt拋出HaltException),將調用catchcradleHalt,我們將轉至renderHaltException,它將設置響應狀態碼。

當你不打電話給halt,但直接返回ActionResult時,情況並不完全相同。在這種情況下,executeRoutes似乎會產生一個值,然後傳遞給renderResponse,然後和renderPipelineThis block似乎是從ActionResult實際設置的實際狀態碼的地方。但是,after函數已被調用(它在actionResult中被調用,在executeRoutes返回之前)。所以你得到的就是你的行爲:當你不使用halt時,正確的響應狀態只在實際響應中設置,而不是在你的日誌記錄調用中設置。

您可能已經嘗試過這種方式,但在您登錄時不會生成正確的HTTP狀態碼的快速解決方法是將其包裝在另一個halt調用中。

至於這是否是一個bug,我不能說。我猜可能不會,因爲他們在executeRoutes文件中確實說過afteractionResult傳遞到renderResponse之前被調用。不清楚的是,渲染actionResult的行爲還設置了您以前要記錄的HTTP錯誤代碼。

你必須與他們確認:)。

+0

感謝您的詳細解釋。我確實打開了一個錯誤,但還沒有收到消息。我現在的解決方法是用halt()來包裝所有東西。 – Aliza