Issue
This Content is from Stack Overflow. Question asked by Will Osborne
I’m writing a simple URL shortener in Clojure, using Ring, Compojure, clojure.java.jdbc
and MySQL.
I’m seeing a very strange issue where some inputs seem to randomly become null midway through a function, causing my checks to fail.
My code:
(defn redirect-handler [slug]
(if (not slug)
(response/bad-request "Must provide slug."))
(let [mapping (db/get-slug slug)]
;; this passes fine
(if mapping
(println (str mapping)))
;; this always calls the else case for some slugs, but not others
(if mapping
(response/redirect (:url mapping))
(do
(println "Not running. Mapping: " mapping)
(response/not-found (str "Slug not found: " slug))))))
For certain inputs, it always returns 404 with “Slug not found: “. Logs reveal very strange behaviour:
{:slug "eel", :url "eel.com"}
Not running. Mapping: nil
And the response is 404 with message Slug not found: eel.com
– even stranger, since it seems to be returning the url instead of the slug in the response. It’s almost as though the data is being modified midway through the function.
I have already confirmed the data in the database is correct.
My DB code:
(def mysql-db (edn/read-string (slurp "env.edn")))
(def query-slug-sql "SELECT * FROM urls WHERE slug = ?")
(defn get-slug [slug]
(first (j/query mysql-db [query-slug-sql slug])))
My HTTP routing code:
(defroutes app-routes
(GET "/:slug" [slug] (redirect-handler slug))
(GET "/" [] (response/not-found "Must provide slug."))
(POST "/create" [slug url] (create-handler slug url)))
(def app
(-> app-routes
(json/wrap-json-params)
(json/wrap-json-response)))
Any idea what is happening here?
Solution
I understand your confusion, because given the code you posted, a single call to redirect-handler
can’t possibly produce those log messages, no matter what value it receives as argument, and no matter what is returned by db/get-slug
. Local variables just can’t change value at all, and there’s no single value in Clojure that goes from truthy to falsey, ever.
I can think of two explanations (maybe there are others):
- The code you posted isn’t the code that’s running. Maybe you rewrote the function but didn’t reload it, for example.
- The log message isn’t exclusively coming from
redirect-handler
. Maybe some other function prints the map on line one, and then the second line is the only thing printed byredirect-handler
.
This Question was asked in StackOverflow by Will Osborne and Answered by amalloy It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.