This commit is contained in:
@@ -3,10 +3,16 @@
|
||||
[clojure.tools.logging :as l]
|
||||
[hiccup2.core :as hiccup]
|
||||
[net.deertopia.doerg.html :as doerg-html]
|
||||
[net.deertopia.publisher.slug :as slug]
|
||||
[org.httpkit.server :as http]
|
||||
[reitit.coercion]
|
||||
[reitit.coercion.spec]
|
||||
[reitit.ring]
|
||||
[ring.util.response :as response]))
|
||||
|
||||
|
||||
;;; Routes
|
||||
|
||||
(defn hello [req]
|
||||
(-> (hiccup/html {}
|
||||
[:html
|
||||
@@ -22,9 +28,27 @@
|
||||
response/response
|
||||
(response/content-type "text/html")))
|
||||
|
||||
(defn node-by-slug [req]
|
||||
(hello req))
|
||||
|
||||
(defn node-by-id [req]
|
||||
(hello req))
|
||||
|
||||
(def router
|
||||
(reitit.ring/router
|
||||
#{["/" {:get hello}]}))
|
||||
#{["/" {:get hello}]
|
||||
["/n/:slug" {:get node-by-slug
|
||||
#_#_#_#_:coercion reitit.coercion.spec/coercion
|
||||
:parameters {:path {:slug ::slug/slug}}}]
|
||||
["/id/:id" {:get node-by-id}]}
|
||||
#_{:compile reitit.coercion/compile-request-coercers}))
|
||||
|
||||
(defn match-by-path-and-coerce! [path]
|
||||
(if-let [match (r/match-by-path router path)]
|
||||
(assoc match :parameters (reitit.coercion/coerce! match))))
|
||||
|
||||
|
||||
;;; Server API
|
||||
|
||||
(def app (reitit.ring/ring-handler router))
|
||||
|
||||
|
||||
66
publisher/src/net/deertopia/publisher/slug.clj
Normal file
66
publisher/src/net/deertopia/publisher/slug.clj
Normal file
@@ -0,0 +1,66 @@
|
||||
(ns net.deertopia.publisher.slug
|
||||
(:require [clojure.spec.alpha :as s])
|
||||
(:import (java.nio ByteBuffer)
|
||||
(java.util Base64 UUID)))
|
||||
|
||||
(defrecord Slug [slug-string]
|
||||
Object
|
||||
(toString [this]
|
||||
(:slug-string this)))
|
||||
|
||||
(defn from-string [s]
|
||||
(try (let [decoder (Base64/getUrlDecoder)]
|
||||
(when (= 16 (count (.decode decoder s)))
|
||||
(Slug. s)))
|
||||
(catch IllegalArgumentException e
|
||||
(when (not= (ex-message e)
|
||||
(str "Input byte[] should at least "
|
||||
"have 2 bytes for base64 bytes"))
|
||||
(throw e)))))
|
||||
|
||||
(defn to-string [s]
|
||||
(str s))
|
||||
|
||||
(defn- coerce-to-uuid [string-or-uuid]
|
||||
(cond (string? string-or-uuid) (UUID/fromString string-or-uuid)
|
||||
(uuid? string-or-uuid) string-or-uuid))
|
||||
|
||||
(defn- uuid->bytes [string-or-uuid]
|
||||
(let [uuid (coerce-to-uuid string-or-uuid)]
|
||||
(.array (doto (ByteBuffer/wrap (byte-array 16))
|
||||
(.putLong (.getMostSignificantBits uuid))
|
||||
(.putLong (.getLeastSignificantBits uuid))))))
|
||||
|
||||
(defn- bytes->uuid [bytes]
|
||||
(when (= (count bytes) 16)
|
||||
(let [bb (ByteBuffer/wrap bytes)
|
||||
high (.getLong bb)
|
||||
low (.getLong bb)]
|
||||
(UUID. high low))))
|
||||
|
||||
(defn from-uuid [string-or-uuid]
|
||||
(let [uuid (coerce-to-uuid string-or-uuid)
|
||||
encoder (.withoutPadding (Base64/getUrlEncoder))]
|
||||
(Slug. (.encodeToString encoder (uuid->bytes uuid)))))
|
||||
|
||||
(defn to-uuid [slug]
|
||||
(let [decoder (Base64/getUrlDecoder)]
|
||||
(bytes->uuid (.decode decoder (str slug)))))
|
||||
|
||||
#_
|
||||
(let [uuid #uuid "f9eab66e-7773-4b87-b854-0bfc8f563809"
|
||||
slug (from-uuid uuid)
|
||||
round-tripped (to-uuid slug)]
|
||||
{:uuid uuid, :slug slug, :round-tripped round-tripped})
|
||||
|
||||
(defn make-slug [string]
|
||||
(assert (try (to-uuid string)
|
||||
(catch Throwable _
|
||||
nil))
|
||||
"invalid slug")
|
||||
(->Slug string))
|
||||
|
||||
(defn slug? [s]
|
||||
(some? (from-string s)))
|
||||
|
||||
(s/def ::slug slug?)
|
||||
Reference in New Issue
Block a user