(set-env! :dependencies '[[ring/ring-core "1.5.0"]
[ring-simpleweb-adapter "0.2.0"]
[compojure "1.5.2"]
[clj-http "2.3.0"]])
;;; more info: https://github.com/weavejester/compojure/wiki
;;; http server stuff
(require '[ring.adapter.simpleweb]
'[compojure.core :refer :all]
'[compojure.route :as route])
;;; http client stuff
(require '[clj-http.client :as http]
'[clojure.java.browse :refer [browse-url]])
;;; * BASIC
(def conn
(-> (routes
(GET "/" []
"<h1>Hello World.</h1>"))
(ring.adapter.simpleweb/run-simpleweb
{:port 8080})))
(:body (http/get "http://localhost:8080/"))
;; => "<h1>Hello World.</h1>"
(browse-url "http://localhost:8080/")
(.close conn)
;;; * RUN WITHOUT ring(WEB SERVER)
(let [app (routes (GET "/" []
"<h1>Hello World.</h1>"))]
(app {:uri "/" :request-method :get}))
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "<h1>Hello World.</h1>"}
;;; * NAME RING APP WITH `defroutes`
(defroutes app
(GET "/" ring-request
(do (str "<h1>Hello World. (" (:uri ring-request) ")</h1>")))
(route/not-found
(do "<h1>Page not found</h1>")))
(app {:uri "/" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "<h1>Hello World</h1>"}
(app {:uri "/" :request-method :post})
;; => {:status 404, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "<h1>Page not found</h1>"}
(def conn
(ring.adapter.simpleweb/run-simpleweb
app {:port 8080}))
(http/get "http://localhost:8080/")
(.close conn)
;;; * NAMED PARAMETERS
(defroutes app
(GET "/hello/:name" [name]
(str "Hello " name)))
(app {:uri "/hello/taro" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "Hello taro"}
(app {:uri "/hello/john" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "Hello john"}
;;; * NAMED PARAMETERS WITH MATCHING REGEX
(defroutes app
(GET ["/file/:name.:ext" :name #".*", :ext #"(txt|md)"] [name ext]
(str "File: " name \. ext)))
(app {:uri "/file/error.txt" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "File: error.txt"}
(app {:uri "/file/error.md" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "File: error.md"}
(app {:uri "/file/error.log" :request-method :get})
;; => nil
;;; * USING NAMED PARAMETERS AND RING-REQUEST
(defroutes app
(GET "/hello/:name" {{name :name} :route-params
uri :uri
:as ring-request}
(str uri ": Hello " name)))
(app {:uri "/hello/taro" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "/hello/taro: Hello taro"}
(app {:uri "/hello/john" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "/hello/john: Hello john"}
;;; COERCE NAMED PARAMETERS
(require 'compojure.coercions)
(defroutes app
(GET "/id/:num" [num :<< compojure.coercions/as-int]
(str (* 2 num))))
(app {:uri "/id/4" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "8"}
(app {:uri "/id/r" :request-method :get})
;; => nil
;;; * QUERY STRING
(require '[ring.middleware.params])
(defroutes app
(GET "/posts" {{:strs [title author]} :query-params
:as req}
(str "Title: " title ", Author: " author)))
(def conn
(-> app
ring.middleware.params/wrap-params
(ring.adapter.simpleweb/run-simpleweb
{:port 8080})))
(app {:uri "/posts" :request-method :get})
;; => {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body "Title: , Author: "}
(app {:uri "/posts?title=Capital&author=Karl%20Heinrich%20Marx" :request-method :get})
;; => nil
(:body (http/get "http://localhost:8080/posts?title=Capital&author=Karl%20Heinrich%20Marx"))
;; => "Title: Capital, Author: Karl Heinrich Marx"
(.close conn)
;;; * STATIC FILES
(require '[clojure.java.io :as io])
(do
(.mkdirs (io/file "res" "css"))
(spit (io/file "res" "css" "style.css") "h1 {background-color: #ccc;}"))
(defroutes app
(route/files "/"
{:root "res"}))
;;; `compojure.route/resources` is also available,
;;; to provide files in classpath instead of file-system.
(def conn
(ring.adapter.simpleweb/run-simpleweb app {:port 8080}))
(http/get "http://localhost:8080/css/style.css")
#_{:status 200,
:headers
{"Content-Length" "28",
"Last-Modified" "Mon, 06 Mar 2017 10:11:36 GMT",
"Content-Type" "text/css",
"Connection" "close"},
:body "h1 {background-color: #ccc;}",
:request-time 6,
:trace-redirects ["http://localhost:8080/css/style.css"],
:orig-content-encoding nil}
(do
(io/delete-file (io/file "res" "css" "style.css"))
(io/delete-file (io/file "res" "css"))
(io/delete-file (io/file "res")))
(.close conn)