Skip to content

Instantly share code, notes, and snippets.

@ptn
Last active August 29, 2015 13:56
Show Gist options
  • Save ptn/9007407 to your computer and use it in GitHub Desktop.
Save ptn/9007407 to your computer and use it in GitHub Desktop.
(ns router.core
(:gen-class)
(:use [clojure.string
:only [replace]
:rename {replace str-replace}]))
(defn- build-route [[url-spec handler]]
(let [regex (re-pattern (str-replace url-spec #":.+?\/" "(.+?)/"))]
`(fn [url#]
(if-let [match# (re-matches ~regex url#)]
(if (coll? match#)
(fn [] (apply ~handler (drop 1 match#)))
(fn [] (~handler)))))))
(defn not-found [] (println "404 Not Found"))
(defmacro defroutes [& route-forms]
(let [handlers (map build-route (partition 2 route-forms))]
`(def routes [~@handlers (fn [url#] (fn [] (not-found)))])))
(defroutes
"/router/both/" (fn [] (println "router both"))
"/only/controller/" (fn [] (println "only controller"))
"/router/params/:x/:y/:z/" (fn [x y z] (println x y z)))
(defmacro with-handler [[var url] & body]
`(let [url# ~url
handler# (some #(% url#) routes)
~var handler#]
(do ~@body)))
(defn route [url]
(with-handler [handler url]
(handler)))
(defn -main [& args]
(route "/router/both/")
(route "/only/controller/")
(route "/router/params/1/2/3/")
(route "NOPE"))
@ptn
Copy link
Author

ptn commented Feb 14, 2014

This is supposed to be the routing component of a web framework - so think Compojure. The user api is only this: defroutes takes strings and functions, interleaved; route calls the handler associated with that url, or not-found if none exists. Still no support for http methods or actual request/response "objects." Here's what lein run should output:

router  [master] $ lein run
router both
only controller
1 2 3
404 Not Found

I'd like the opinion of someone who knows Clojure better than I do, cause this is probably not very idiomatic. I'm mostly bothered by the very deep indentation in build-route, which may be solvable by some magic Clojure incantation that I don't know.

@ptn
Copy link
Author

ptn commented Feb 14, 2014

:10s/if-let/when-let/g

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment