clojure blog 2: HTTP routing (ring / compojure)

Ring: HTTP requests.


EDIT: There are a million ways to handle HTTP routing in Clojure: Ring, bidi, pedestal, playnice, gudu, Route One (to name some I found on google) and there may be many more that I don't know. Some are closer to the Clojure idea of data above all, but I chose Compojure. Seems to be the most popular, and that falls in line with my new restaurant routine: order the most popular item, because sometimes there's wisdom in the crowd.

Ring is a simple request handler based off Python's WSGI and Ruby's Rack. It can handle only very basic HTTP requests. If you search up Ring on Google, you'll come up with basically the same example over and over again, and it is a static single page application to show how the basic request system works. It goes something like this:
;; project.clj (defproject ring-example "1.0"     :description "this is the most basic example"     :dependencies [[org.clojure/clojure "1.9.0"]                    [ring/ring-core "1.6.3"]                    [ring/ring-jetty-adapter "1.6.3"]]     :main solb.example-project)
;; src/solb/ring.clj (ns solb.ring     (:require [ring.adapter.jetty :refer [run-jetty]])) (defn handler     [request]     {:status 200      :headers {"Content-Type" "text/html"}      :body "this is the example."}) (defn -main [& args]     (run-jetty handler {:port 5000}))
This beautiful piece of example can be grabbed from Github (if you really want it for whatever reason) and ran with lein run in the main directory. Then navigate over to localhost:5000 and you should see your beautiful "this is the example." string. If you really fancied yourself a hacker, you could build your own routing system with only this library, but personally I'd rather have a little bit more built for me; which is why most use a library like Compojure.
λλλ

Compojure: routing.

Let's take a look at something a little more interesting: Compojure. This is how one would really build a webapp in Clojure as Compojure is a much more all-encompassing routing tool with most of the features you'd really want. Let's take a look with a little example: (which can also be found here on my Github).
;; project.clj
(defproject compojure-example "1.0.0" :description "this is the most basic example" :dependencies [[org.clojure/clojure "1.9.0"] [compojure "1.6.1"] [ring/ring-core "1.7.1"] [ring/ring-jetty-adapter "1.7.1"]] :main solb.compojure :plugins [[cider/cider-nrepl "0.21.1"]])
;; src/solb/compojure.clj
(ns solb.compojure (:require [compojure.core :refer :all] [compojure.route :as route] [ring.middleware.params :refer [wrap-params]] [ring.adapter.jetty :as jetty])) (defroutes app-routes (GET "/" [] "main page here!!") (GET "/user/:id" [id] (str "hihihi " id)) (POST "/post" [:as req] (str (:params req))) (route/not-found "404 page")) (def app (-> app-routes (wrap-params))) (defonce server (jetty/run-jetty #'app {:port 5000 :join? false})) (defn stop-server [] (.stop server)) (defn -main [& args] (.start server))
This shows the basics of routing. GET, and POST routes, and how to play a little bit with params. A few curl's can show what we can do with Compojure.
$> curl localhost:5000
main page here!!
We also see that destructuring route (GET "/user/:id" [id] (str "hihihi " id)). This is of course quite an important feature of a website. My example is merely the simplest syntax, but there are many forms of destructuring syntax on the here on the Compojure github.
$> curl localhost:5000/user/solb
hihihi sol
Cool! Now to play with the POST route; located at the "/post" endpoint.
$> curl -X POST -d "name=solly&hobby=coding" localhost:5000/post
{"name" "solly", "hobby" "coding"}
To use params, you have to wrap the handler with wrap-params, there are other ways to wrap parameters (such as wrap-multiparts-params) but this is a simple one that works with the url-encoded parameters.

Now that we have the basics of HTTP request systems, we can start really building something. We have a foundation to build on. In the next post I will play with Compojure a little more, but will also use Hiccup; the defacto way to compile Clojure down to HTML.