herokuでclojure appを作る
公式のGetting Started on Heroku with Clojureに従う。 英語しんどい。。。しんどい。。。
ローカルで動かす
別に git push heroku master
でherokuに上げなくても、ローカルで試せる。
これも公式が説明してくれる。 英語に慣れてないので見つけにくい
Heroku Dev Center - Getting Started on Heroku with Clojure: Run the app locally
僕はspacemacsを使っていたので、 cider-jack-in
でreplを開いてから公式のように (require 'clojure-getting-started.web)
=> (def server (clojure-getting-started.web/-main))
した。
ファイルを書き換えてサーバに反映したいときは Space e b
でバッファごと評価し直すといけた。
herokuに送り込むのも、なんかmagitでcommitした後に P e
heroku/master
って選んでいったらできた。なにもわからない。
JSONを返す
公式のサンプルコードでは、プレーンテキストだけを返す簡単な構成となっている(404とかはhtmlを返している模様?)
JSONも返したい。 正直なにもわからない
コード
試行錯誤の末こうなった。 clojure-getting-started
ディレクトリ下で project.clj
と src/clojure_getting_started/web.clj
の2ファイルを書き換える。
(defproject clojure-getting-started "1.0.0-SNAPSHOT"
:description "Demo Clojure web app"
:url "http://clojure-getting-started.herokuapp.com"
:license {:name "Eclipse Public License v1.0"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.10.0"]
[compojure "1.6.1"]
[ring/ring-jetty-adapter "1.7.1"]
[ring/ring-json "0.5.0"] ; JSONを扱うために追加
[environ "1.1.0"]]
:min-lein-version "2.0.0"
:plugins [[environ/environ.lein "0.3.1"]]
:hooks [environ.leiningen.hooks]
:uberjar-name "clojure-getting-started-standalone.jar"
:profiles {:production {:env {:production true}}})
(ns clojure-getting-started.web
(:require [compojure.core :refer [defroutes GET PUT POST DELETE ANY]]
[compojure.handler :refer [site]]
[compojure.route :as route]
[clojure.java.io :as io]
[ring.adapter.jetty :as jetty]
[ring.middleware.json :refer [wrap-json-response]]
[environ.core :refer [env]]))
(defn splash []
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello from Heroku"})
(defn my-json-response []
{:status 200
:headers {"Content-Type" "application/json;charset=utf-8"}
:body {:name "v2okimochi"
:version 2
:state "( '・ω・`)"}})
(defroutes app
(GET "/" []
(splash))
(GET "/please-json" []
(my-json-response)) ; JSONを返す場合
(ANY "*" []
(route/not-found (slurp (io/resource "404.html")))))
(defn -main [& [port]]
(let [port (Integer. (or port (env :port) 5000))]
(jetty/run-jetty (-> (site app)
(wrap-json-response))
{:port port :join? false}))) ; JSONを返せる実装
;; For interactive development:
;; (.stop server)
;; (def server (-main))
差分
増えたところと減ったところ。インデントはゆるして。
(defproject clojure-getting-started "1.0.0-SNAPSHOT"
:description "Demo Clojure web app"
:url "http://clojure-getting-started.herokuapp.com"
:license {:name "Eclipse Public License v1.0"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.10.0"]
[compojure "1.6.1"]
[ring/ring-jetty-adapter "1.7.1"]
+ [ring/ring-json "0.5.0"] ; JSONを扱うために追加
[environ "1.1.0"]]
:min-lein-version "2.0.0"
:plugins [[environ/environ.lein "0.3.1"]]
:hooks [environ.leiningen.hooks]
:uberjar-name "clojure-getting-started-standalone.jar"
:profiles {:production {:env {:production true}}})
(ns clojure-getting-started.web
(:require [compojure.core :refer [defroutes GET PUT POST DELETE ANY]]
[compojure.handler :refer [site]]
[compojure.route :as route]
[clojure.java.io :as io]
[ring.adapter.jetty :as jetty]
+ [ring.middleware.json :refer [wrap-json-response]]
[environ.core :refer [env]]))
(defn splash []
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello from Heroku"})
+ (defn my-json-response []
+ {:status 200
+ :headers {"Content-Type" "application/json;charset=utf-8"}
+ :body {:name "v2okimochi"
+ :version 2
+ :state "( '・ω・`)"}})
(defroutes app
(GET "/" []
(splash))
+ (GET "/please-json" []
+ (my-json-response)) ; JSONを返す場合
(ANY "*" []
(route/not-found (slurp (io/resource "404.html")))))
(defn -main [& [port]]
(let [port (Integer. (or port (env :port) 5000))]
- (jetty/run-jetty (site #'app) {:port port :join? false}) ; サンプルでの実装
+ (jetty/run-jetty (-> (site app)
+ (wrap-json-response))
+ {:port port :join? false}))) ; JSONを返せる実装
;; For interactive development:
;; (.stop server)
;; (def server (-main))
実際に叩くとこう
ローカルならlocalhost:5000/
で繋がる。ルートならサンプル通りのテキストが返る。
新たに作った localhost:5000/please-json
にアクセスすると、ちゃんとJSONを返してくれる。
ちなみにこういうAPIサーバっぽいのに接続するときにはpostman使うのおすすめ。結果がわかりやすいしヘッダ情報とかも見られる。
{
"name": "v2okimochi",
"version": 2,
"state": "( '・ω・`)"
}
なおコードにあった :headers
は無くてもよろしくやってくれた。でも指定すると安心。
JSON返すだけで (調べるのが) たいへん。メモしとかないと書いてるそばからもう既に忘れている。
まとめ
- herokuのclojure-getting-startedコードを拡張してJSON返せるようになった
なんでこうなるのかわかりてえなあ