音楽とプログラムと

基本的に散文。音楽とか、プログラムとか。

clojureのroutingライブラリでbidiがわからなかったのでreititを使ったら楽だった。

clojureでWebアプリを作る方法をしらべるとDuctがよく出てくるのだが、

github.com

元となっているRingを手で動かして理解したかったので、Ductは使わずに簡単なAPIを書きながらチョコチョコやってた。

こちらの記事には大変お世話になった。おかげでhandlerとmiddlewareを完全に理解した。

tech.toyokumo.co.jp

さて、routingのライブラリでbidiで紹介されていたのでそれを使ってゴニョゴニョやっていたのだが、なぜか思うようにいかないルーティングがあり、githubのドキュメントや、書いてあるtestをみたりしていたのだが、ちょっと痒いところに(知りたいところ)手がとどかない。

reititというのがブログの中やqiitaの記事でお見かけし、またググってみると以下の記事 でもなかなかお勧めされてたのでDocumentを読んでみた。

purelyfunctional.tv

Documentがわかりやすく、丁寧な感じで、またmiddlewareの適用のさせ方もなかなか素敵な感じがした。

cljdoc.org

ring-routerというものを使えばうまくいきそう。

早速使ってみるとなかなかいい感じ。 前まで 以下のような感じでmiddlewareを適用させてた。 書き方が悪い?か他の書き方もあるかもしれないが、以下だと、どのリクエストできても全てのmiddlewareを通過してしまう。 handlerごとに別のものを適用させたいときどうするのかな?と思いつつ今のところはそのままでよかったので後回しにしていた。

今まで。以下のような感じ
(def app
     (->
       (make-handler route) ;; routeは別で定義する。bidi使用
       (logger/wrap-with-logger)
       (wrap-json-response)
       (wrap-default-charset "utf-8")
       (wrap-oauth2
         (provider/profile
           {:service-provider :gmail
            :environment      environment}))
       (wrap-cookies)
       (wrap-verify-token)
       (wrap-store-session-token)
       (wrap-session)
       (wrap-keyword-params)
       (wrap-params)
       (r.m.cors/wrap-cors :access-control-allow-origin [#"https://.*localhost:8280" #"https://account.google.com" #"https://www.googleapis.com"]
                           :access-control-allow-headers #{:accept :content-type :authorization}
                           :access-control-allow-methods #{:get :put :post :delete :options :head})))

reititを使うと以下のようになる。

reitit使用

(def default-wrappers
     [[r.m.cors/wrap-cors :access-control-allow-origin [#"https://.*localhost:8280" #"https://account.google.com" #"https://www.googleapis.com"]
       :access-control-allow-headers #{:accept :content-type :authorization}
       :access-control-allow-methods #{:get :put :post :delete :options :head}]
      [wrap-params]
      [wrap-session]
      [wrap-store-session-token]
      [wrap-verify-token]
      [wrap-cookies]
      [wrap-oauth2 (provider/profile
                     {:service-provider :gmail
                      :environment      environment})]
      [wrap-default-charset "utf-8"]
      [wrap-json-response]
      [logger/wrap-with-logger]]

(def app
     (ring/ring-handler
       router
       (constantly {:status 404 :body ""})
       {:middleware default-wrappers})) 
;; この書き方では default-wrappersは全てのルーティングに適用される。

上記では すべてのリクエスト pathに対してdefault-wappersが適用されるが 以下のようにhandlerごとにmiddlewareも適用できるみたいだ。

(def reitit-router
     (ring/router
       ["/" {:middleware [[wrap-json-response]]
               :get route-handler}
          ["login" {:post login-handler
                         :middleware [[wrap-login]] }))

素敵だ。

clojureはライブラリを適用させていく感じがプラモデルを作るようで面白いんだが、Documentがわかりにくいというか、素っ気ない物も多いので(その場合 grep.app で github内の使用方法をみたり、testコードをみたり、slackで検索したりする。)Documentがいい感じなだけで使う意欲がもっとわく。(re-frameもDocumentがいい)

しばらくこれを使って遊んでみよう。