basic http requests and server handlers in clojure
- 2 minutes read - 334 wordsI’ve been playing around a tiny bit with clojure, and wanted to document the process of doing something pretty basic: make a project that can request my website over HTTPs.
The first step is pretty easy:
brew install leiningen
lein new random-experimentation
cd random-experimentation
and add [clj-http "3.4.1"]
to project.clj
.
The HTTPS part is a bit trickier. The JDK doesn’t include the Letsencrypt certificates. But I found a simple script install-letsencrypt-in-jdk.sh that can set it up.
wget https://gist.githubusercontent.com/Firefishy/109b0f1a90156f6c933a50fe40aa777e/raw/15926be913682876ae68bb4f71e489bc53feaae3/install-letsencrypt-in-jdk.sh
sudo install-letsencrypt-in-jdk.sh $(...)
With that in place, it’s possible to start a lein repl
and make a request:
$ lein repl
user=> (require '[clj-http.client :as client])
user=> (client/get "https://traviscj.com/_status.json")
{:request-time 877, :repeatable? false, :protocol-version {:name "HTTP", :major 1, :minor 1}, :streaming? true, :chunked? false, :reason-phrase "OK", :headers {"Server" "nginx/1.10.0 (Ubuntu)", "Date" "Thu, 02 Feb 2017 03:55:23 GMT", "Content-Type" "application/json", "Content-Length" "27", "Last-Modified" "Mon, 01 Aug 2016 02:31:03 GMT", "Connection" "close", "ETag" "\"579eb467-1b\"", "Strict-Transport-Security" "max-age=15768000", "Accept-Ranges" "bytes"}, :orig-content-encoding nil, :status 200, :length 27, :body "{\n \"site\":\"traviscj.com\"\n}", :trace-redirects ["https://traviscj.com/_status.json"]}
user=> (def status (client/get "https://traviscj.com/_status.json"))
#'user/status
user=> (:body status)
"{\n \"site\":\"traviscj.com\"\n}"
With a bit more repl-experimentation and judicious reloading, we can make a small script that applies a similar GET
to a list of sites:
(ns random-experimentation.core
(:require [clj-http.client :as client]))
(def sites [
"traviscj.com"
"pauljoos.com"
"jdbeals.com"
"thingsworthkeeping.com"
"bovineherdhealth.com"
])
(defn get-status [site]
(defn get-status-url [site]
(str "https://" site "/_status.json"))
(defn get-status-json [site]
(client/get (get-status-url site) {:as :json}))
[site (:status (get-status-json site))])
;; lein run -m random-experimentation.core
(defn -main []
(println (map get-status sites))
)
and use that within a new:
(use 'random-experimentation.core)
or existing:
(use 'random-experimentation.core :reload)
repl session.
I also tried out spinning up an HTTP server and responding to a request.
This is also pretty easy; one must :require
an additional module
[ring.adapter.jetty :as j]
and define a handler:
(defn handler [request]
(println request)
{:status 200
:headers {"Content-Type" "text/html"}
:body (str "Hello World blah!" (:uri request))})
and j/run-jetty
wtih that handler (and a particular port, of course):
(defn -main []
(j/run-jetty handler {:port 3001}))
Pretty slick!