昨日は作ったTodoアプリのログが出せるようになりました
今日はエラーのハンドリングを行います
今日もエラーをキャッチするようなミドルウェアを作成してみます
ミドルウェア作成
wrap-error-handling
という名前のミドルウェアを作成し、エラーハンドリングしてみようと思います
今回は以下2パターンに関してエラーを実装していこうと思います
-
clojure.lang.ExceptionInfo
の時は実装されたエラーを返す - それ以外の例外ケースは500エラーを返す
core.clj
(defn wrap-error-handling
[handler]
(fn [req]
(try
(handler req)
(catch clojure.lang.ExceptionInfo e
(let [{:keys [status]} (ex-data e)
message (ex-message e)]
(res/status (res/response {:message message}) status)))
(catch Exception e
(let [message (str "Internal Server Error: " (.getMessage e))]
(res/status (res/response {:message message}) 500))))))
こんな感じで実装してみました
実際に GET /v1/todos/{id}
で存在しないTodoを指定したときには404エラーになるようにしてみます
handler.clj
(defn get-todo [id]
(-> (driver/find-todo id)
(or (throw (ex-info (str "Todo id: " id ", Not found") {:status 404})))
(res/response)))
これでTodoがなかった時にはclojure.lang.ExceptionInfo
を throw
するようにできました
実際にリクエストを送ってみます
# 存在する場合
$ curl localhost:3000/v1/todos/1 -v
* Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /v1/todos/1 HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 16 Dec 2024 13:43:07 GMT
< Content-Type: application/json;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(11.0.24)
<
* Connection #0 to host localhost left intact
{"id":1,"title":"朝食を食べる","completed":false}
# 存在しない場合
$ curl localhost:3000/v1/todos/123 -v
* Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /v1/todos/123 HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Date: Mon, 16 Dec 2024 13:42:46 GMT
< Content-Type: application/json;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(11.0.24)
<
* Connection #0 to host localhost left intact
{"message":"Todo id: 123, Not found"}
存在するTodoを取るときは200
、
存在しない場合は404
エラーになりました