diff --git a/resources/app/stylesheets/app.less b/resources/app/stylesheets/app.less index 40075f9..8197d83 100644 --- a/resources/app/stylesheets/app.less +++ b/resources/app/stylesheets/app.less @@ -106,15 +106,14 @@ img, svg { display: grid; grid-template-columns: 40% 60%; align-items: center; - margin-top: 0; - background-color: ThreeDShadow; + margin: 0 @element-margin; //noinspection CssUnknownTarget background-image: url("/img/logo-full-flipped.svg"); background-size: contain; background-position: right; background-origin: content-box; background-repeat: no-repeat; - border-bottom: 1px solid @ci-highlight; + border-bottom: 1px solid @ci-color; .app-title { grid-column: 1; @@ -140,8 +139,10 @@ img, svg { nav { grid-area: nav; - background-color: Window; - padding-right: 0; + padding-right: @element-margin; + border-right: 1px solid @ci-color; + margin-top: @element-margin; + margin-left: @element-margin; h2::before { content: "▤ "; diff --git a/resources/app/stylesheets/devmode.less b/resources/app/stylesheets/devmode.less deleted file mode 100644 index 1638ed2..0000000 --- a/resources/app/stylesheets/devmode.less +++ /dev/null @@ -1,24 +0,0 @@ -.devbar { - position: fixed; - bottom: 0; - left: 0; - width: 100%; - font-family: monospace; - background-color: #ccc; - - ol { - list-style-type: none; - padding: 0; - margin: 0; - - li { - padding: .5rem; - border: 1px solid black; - margin: .5rem; - - pre { - margin: 0; - } - } - } -} diff --git a/src/wanijo/handler.clj b/src/wanijo/handler.clj index 0dbb64e..7aa6677 100644 --- a/src/wanijo/handler.clj +++ b/src/wanijo/handler.clj @@ -1,5 +1,6 @@ (ns wanijo.handler - (:require [compojure.core + (:require [clojure.string :refer [starts-with?]] + [compojure.core :refer [defroutes routes]] [compojure.route :as route] [ring.middleware.defaults @@ -19,8 +20,9 @@ [wanijo.tag.routes :as tag-routes] [wanijo.infrastructure [auth :as auth] - [devmode :as devmode] - [routing :refer [path]]])) + [routing :refer [path]] + [gzip :as gzip] + [neo4j :as neo4j]])) (defn- wrap-login-redirect [handler] (fn [req] @@ -44,7 +46,8 @@ (-> app-routes schema-middleware/wrap-user-schemas! ring-json/wrap-json-response - (wrap-defaults site-defaults))) + (wrap-defaults site-defaults) + gzip/wrap-gzip)) (defn wrap-spec-asserts [handler] (fn [req] @@ -54,11 +57,11 @@ (def dev-app (-> app-routes wrap-spec-asserts - devmode/wrap-devmode schema-middleware/wrap-user-schemas! ring-json/wrap-json-response (wrap-defaults (assoc-in site-defaults [:session :store] (session-cookie/cookie-store - {:key "1234567890123456"}))))) + {:key (subs (neo4j/uuid) 0 16)}))) + gzip/wrap-gzip)) diff --git a/src/wanijo/infrastructure/devmode.clj b/src/wanijo/infrastructure/devmode.clj deleted file mode 100644 index 7589508..0000000 --- a/src/wanijo/infrastructure/devmode.clj +++ /dev/null @@ -1,46 +0,0 @@ -(ns wanijo.infrastructure.devmode - (:require [hiccup.core :as hcore] - [clojure.string :as cljs])) - -(def bar-entries (atom [])) - -(defn send-to-bar [msg] - (swap! bar-entries #(conj % msg))) - -(defn devmode-on? [req] - (let [query-param (get-in req [:query-params "dev"]) - cookie (get-in req [:cookies "devmode" :value])] - (or (= query-param "on") - (and (= cookie "1") - (not= query-param "off"))))) - -(defn devbar [resp] - (hcore/html - [:section.devbar - [:ol - (for [entry @bar-entries] - [:li [:pre entry]])]])) - -(defn append-devbar [resp] - (let [body (:body resp) - new-body (cljs/replace - body "" (str (devbar resp) ""))] - (assoc resp :body new-body))) - -(defn wrap-devmode [handler] - (fn [req] - (let [on? (devmode-on? req) - query-param? (get-in req [:query-params "dev"]) - new-req (assoc-in req [:session :devmode] on?) - resp (handler new-req) - new-resp (cond - on? (-> resp - append-devbar - (assoc-in [:cookies :devmode] 1)) - (some? query-param?) (assoc-in - resp - [:cookies :devmode] - (if on? 1 0)) - :else resp)] - (reset! bar-entries []) - new-resp))) diff --git a/src/wanijo/infrastructure/gzip.clj b/src/wanijo/infrastructure/gzip.clj new file mode 100644 index 0000000..babbb1d --- /dev/null +++ b/src/wanijo/infrastructure/gzip.clj @@ -0,0 +1,77 @@ +(ns wanijo.infrastructure.gzip + (:require [clojure.java.io :as io]) + (:import (java.io InputStream + Closeable + File + PipedInputStream + PipedOutputStream) + (java.util.zip GZIPOutputStream))) + +(defn set-response-headers + [headers] + (if-let [vary (or (get headers "vary") (get headers "Vary"))] + (-> headers + (assoc "Vary" (str vary ", Accept-Encoding")) + (assoc "Content-Encoding" "gzip") + (dissoc "Content-Length" "content-length") + (dissoc "vary")) + (-> headers + (assoc "Vary" "Accept-Encoding") + (assoc "Content-Encoding" "gzip") + (dissoc "Content-Length" "content-length")))) + +(defn accepts-gzip? + [req] + (if-let [accepts (get-in req [:headers "accept-encoding"])] + ;; Be aggressive in supporting clients with mangled headers (due to + ;; proxies, av software, buggy browsers, etc...) + (re-seq + #"(gzip\s*,?\s*(gzip|deflate)?|X{4,13}|~{4,13}|\-{4,13})" + accepts))) + +(defn supported-response? [resp] + (let [{:keys [status headers body]} resp + min-bytes 859] + (and + ;; correct status code + (#{200 201 202 203 204 205 403 404} status) + ;; not already encoded + (not (or (headers "Content-Encoding") + (headers "content-encoding"))) + ;; correct data type in body + (or (string? body) + (seq? body) + (instance? InputStream body) + (and (instance? File body) + (re-seq #"(?i)\.(htm|html|css|js|json|xml)" + (pr-str body)))) + ;; sensible body sizes + (cond (string? body) (> (count body) min-bytes) + (seq? body) (> (count body) min-bytes) + (instance? File body) (> (.length body) min-bytes) + :else true)))) + +(defn compress-body [body] + (let [p-in (PipedInputStream.) + p-out (PipedOutputStream. p-in)] + (future + (with-open [out (GZIPOutputStream. p-out)] + (if (seq? body) + (doseq [string body] (io/copy (str string) out)) + (io/copy body out))) + (when (instance? Closeable body) + (.close ^Closeable body))) + p-in)) + +(defn gzip-response [resp] + (-> resp + (update :headers set-response-headers) + (update :body compress-body))) + +(defn wrap-gzip [handler] + (fn [req] + (let [resp (handler req)] + (if (and (accepts-gzip? req) + (supported-response? resp)) + (gzip-response resp) + resp)))) diff --git a/src/wanijo/infrastructure/neo4j.clj b/src/wanijo/infrastructure/neo4j.clj index fdac842..4c9642d 100644 --- a/src/wanijo/infrastructure/neo4j.clj +++ b/src/wanijo/infrastructure/neo4j.clj @@ -1,7 +1,6 @@ (ns wanijo.infrastructure.neo4j (:require [neo4j-clj.core :as db] [neo4j-clj.in-memory :as db-inm] - [wanijo.infrastructure.devmode :as devmode] [clj-time.format :as time-format] [clj-time.local :as time-local] [clojure.spec.alpha :as spec] @@ -64,10 +63,6 @@ (defn exec-query! [qry params] (let [live-conn (or @conn (reset-conn!))] (with-open [session (db/get-session live-conn)] - (devmode/send-to-bar - (str (butiful-query qry) - "
---Params---
" - params)) ;; neo4j-clj returns lazy lists, but when we leave with-open, ;; the ResultSet (?) is already closed, so the list cannot ;; be processed @@ -84,10 +79,6 @@ (doseq [tuple tuples] (let [qry (first tuple) params (second tuple)] - (devmode/send-to-bar - (str (butiful-query qry) - "
---Params---
" - params)) (spec/assert map? params) (qry tx params))))) diff --git a/src/wanijo/infrastructure/view.clj b/src/wanijo/infrastructure/view.clj index 5f5909d..5ed975c 100644 --- a/src/wanijo/infrastructure/view.clj +++ b/src/wanijo/infrastructure/view.clj @@ -35,8 +35,7 @@ head nil}}] (let [session (or session (:session request)) ident (:ident session) - authed? (some? ident) - devmode? (:devmode session)] + authed? (some? ident)] (html5 [:head [:meta {:charset "utf-8"}] @@ -44,7 +43,6 @@ :content "width=device-width,initial-scale=1,shrink-to-fit=no"}] [:title (h (str (when title (str title " - ")) "wanijo"))] (include-css "/css/app.css") - (when devmode? (include-css "/css/devmode.css")) (include-js "/js/scripts.js") head] [:body