clojure と reitit で簡単なAPIをつくってみる
以下のサイトなどを参考にさせてもらって。
Contents
シンプルなサーバー
まず、leininngenで、プロジェクトを作成
lein new user-api
project.cljを開いて、ring の依存を追加。
…
:dependencies [[org.clojure/clojure "1.10.1"]
[javax.servlet/servlet-api "2.5"]
+ [ring "1.9.4"]]
…
とりあえず、ringのみで動かす。
引数にリクエストのマップを受けて、レスポンスのマップを返す関数(ハンドラー)を作成。
まずは、リクエストの内容に関係なく、bodyに"hello world"が入ったレスポンスを返す。
(ns user-api.core
(:require [ring.adapter.jetty :as jetty]))
(defn handler [request]
{:status 200
:headers {"Content-Type" "text/html"}
:body "Hello World"})
(defn start []
(jetty/run-jetty handler {:port 3000
:join? false}))
replからサーバーを起動.
(def server (start))
ターミナルから、HTTPieで動作確認。
> http :3000
HTTP/1.1 200 OK
Content-Length: 11
Content-Type: text/html
Date: Tue, 14 Dec 2021 06:10:18 GMT
Server: Jetty(9.4.42.v20210604)
Hello World
サーバー停止
(.stop server)
ルーターを追加
ルーターライブラリはいろいろあって、チュートリアルでよく見かけるのは、Compojure,Bidi,Ataraxy(ductのとき)あたり?
今回はreititを使用。
project.cljを開いて、reitit を追加して、replを再起動
…
:dependencies […
[metosin/reitit "0.5.15"]
[metosin/muuntaja "0.6.8"]]
…
reitit.ring/ring-router
(ns user-api.core
(:require [ring.adapter.jetty :as jetty]
+ [reitit.ring :as ring]
+ [muuntaja.core :as m]
+ [reitit.ring.middleware.muuntaja :as muuntaja])
(:gen-class))
-(defn handler [_]
+(defn string-handler [_]
+ (def app
+ (ring/ring-handler
+ (ring/router
+ ["/"
+ ["" string-handler]]
+ {:data {:muuntaja m/instance
+ :middleware [muuntaja/format-middleware]}})))
(defn start []
(jetty/run-jetty app {:port 3000 ;handler を app に変更
:join? false}))
ターミナルから、HTTPieで動作確認。
>http :3000
HTTP/1.1 200 OK
Content-Length: 5
Date: Fri, 17 Jun 2022 07:21:13 GMT
Server: Jetty(9.4.42.v20210604)
Hello
post で データを追加
(defonce server (atom nil))
+ (def users (atom {}))
…
+ (defn create-user [{user :body-params}]
+ (let [id (str (java.util.UUID/randomUUID))
+ users (->> (assoc user :id id)
+ (swap! users assoc id))]
+ {:status 201
+ :body (get users id)}))
…
["" string-handler]
+ ["users" {:post create-user}]]
ターミナルから、HTTPieで動作確認。
>http post :3000/users name=alice
HTTP/1.1 200 OK
Content-Length: 58
Content-Type: application/json;charset=utf-8
Date: Fri, 17 Jun 2022 07:40:45 GMT
Server: Jetty(9.4.42.v20210604)
{
"id": "1244f409-f999-427b-97e0-08586e2078c4",
"name": "alice"
}
getでデータの取得
+(defn get-users [_]
+ {:status 200
+ :body @users})
+(defn get-user-by-id [{{:keys [id]} :path-params}]
+ {:status 200
+ :body (get @users id)})
- ["users" {:post create-user}]]
+ ["users" {:get get-users
+ :post create-user}]
+ ["users/:id" get-user-by-id]]
ターミナルから、HTTPieで動作確認。
>http post :3000/users name=alice
…
>http post :3000/users name=bob
…
>http :3000/users/3f005a74-0f4c-4d25-90d0-ca332276247c
HTTP/1.1 200 OK
Content-Length: 60
Content-Type: application/json;charset=utf-8
Date: Fri, 17 Jun 2022 08:07:57 GMT
Server: Jetty(9.4.42.v20210604)
{
"id": "3f005a74-0f4c-4d25-90d0-ca332276247c",
"name": "alice"
}
> http :3000/users
HTTP/1.1 200 OK
Content-Length: 284
Content-Type: application/json;charset=utf-8
Date: Fri, 17 Jun 2022 08:08:57 GMT
Server: Jetty(9.4.42.v20210604)
{
"3f005a74-0f4c-4d25-90d0-ca332276247c": {
"id": "3f005a74-0f4c-4d25-90d0-ca332276247c",
"name": "alice"
},
"b90cec39-bc8e-47d1-8f6c-f2996ef02a02": {
"id": "b90cec39-bc8e-47d1-8f6c-f2996ef02a02",
"name": "bob"
}
}
put、delete
+(defn update-user [{{:keys [id]} :path-params user :body-params}]
+ (swap! users id user)
+ {:status 200
+ :body "updated"})
+(defn delete-user [{{:keys [id]} :path-params}]
+ (swap! users dissoc id)
+ {:status 204
+ :body ""}
)
…
-["users/:id" get-user-by-id]]
+["users/:id" {:get get-user-by-id
+ :put update-user
+ :delete delete-user}]
次はIntegrantを組み込んでみる。
ディスカッション
コメント一覧
まだ、コメントがありません