From 2e0cb5c3ebcc4b268d95d0518bf029892cf2c1ab Mon Sep 17 00:00:00 2001 From: Marcin Kulik Date: Wed, 15 Feb 2017 17:53:19 +0100 Subject: [PATCH] Unify FileStore and FileServer --- dev/resources/dev.edn | 5 +-- dev/src/dev.clj | 4 +- resources/asciinema/system.edn | 10 +---- src/asciinema/boundary/file_server.clj | 4 -- src/asciinema/boundary/file_store.clj | 3 +- src/asciinema/component/local_file_server.clj | 18 --------- src/asciinema/component/local_file_store.clj | 16 +++++++- src/asciinema/component/s3_file_server.clj | 37 ------------------- src/asciinema/component/s3_file_store.clj | 37 ++++++++++++++++++- src/asciinema/endpoint/asciicasts.clj | 6 +-- test/asciinema/boundary/file_server_test.clj | 7 ---- 11 files changed, 59 insertions(+), 88 deletions(-) delete mode 100644 src/asciinema/boundary/file_server.clj delete mode 100644 src/asciinema/component/local_file_server.clj delete mode 100644 src/asciinema/component/s3_file_server.clj delete mode 100644 test/asciinema/boundary/file_server_test.clj diff --git a/dev/resources/dev.edn b/dev/resources/dev.edn index 594b2d4..8173efd 100644 --- a/dev/resources/dev.edn +++ b/dev/resources/dev.edn @@ -1,8 +1,5 @@ {:components - {:file-store #var asciinema.component.local-file-store/local-file-store - :file-server #var asciinema.component.local-file-server/local-file-server} - :dependencies - {:file-server [:file-store]} + {:file-store #var asciinema.component.local-file-store/local-file-store} :config {:app {:middleware diff --git a/dev/src/dev.clj b/dev/src/dev.clj index b720e61..7faf3cf 100644 --- a/dev/src/dev.clj +++ b/dev/src/dev.clj @@ -9,10 +9,10 @@ [duct.util.repl :refer [setup test cljs-repl migrate rollback]] [duct.util.system :refer [load-system]] [reloaded.repl :refer [system init start stop go reset]] - [asciinema.boundary.file-server :as file-server] [asciinema.boundary.file-store :as file-store] + [asciinema.boundary.asciicast-database :as asciicast-database] [asciinema.component.local-file-store :refer [->LocalFileStore]] - [asciinema.component.local-file-server :refer [->LocalFileServer]])) + [asciinema.component.s3-file-store :refer [->S3FileStore]])) (defn new-system [] (load-system (keep io/resource ["asciinema/system.edn" "dev.edn" "local.edn"]))) diff --git a/resources/asciinema/system.edn b/resources/asciinema/system.edn index 2016ee7..e4ba3a6 100644 --- a/resources/asciinema/system.edn +++ b/resources/asciinema/system.edn @@ -3,15 +3,14 @@ :http #var asciinema.component.aleph/aleph-server :db #var asciinema.component.db/hikaricp :ragtime #var duct.component.ragtime/ragtime - :file-store #var asciinema.component.s3-file-store/s3-file-store - :file-server #var asciinema.component.s3-file-server/s3-file-server} + :file-store #var asciinema.component.s3-file-store/s3-file-store} :endpoints {:asciicasts #var asciinema.endpoint.asciicasts/asciicasts-endpoint} :dependencies {:http [:app] :app [:asciicasts] :ragtime [:db] - :asciicasts [:db :file-server]} + :asciicasts [:db :file-store]} :config {:app {:middleware @@ -58,11 +57,6 @@ :ragtime {:resource-path "asciinema/migrations"} :file-store - {:cred {:access-key s3-access-key - :secret-key s3-secret-key} - :bucket s3-bucket - :path-prefix "uploads/"} - :file-server {:cred {:access-key s3-access-key :secret-key s3-secret-key} :bucket s3-bucket diff --git a/src/asciinema/boundary/file_server.clj b/src/asciinema/boundary/file_server.clj deleted file mode 100644 index c380724..0000000 --- a/src/asciinema/boundary/file_server.clj +++ /dev/null @@ -1,4 +0,0 @@ -(ns asciinema.boundary.file-server) - -(defprotocol FileServer - (serve [this path] [this path opts])) diff --git a/src/asciinema/boundary/file_store.clj b/src/asciinema/boundary/file_store.clj index d9107a8..c9fad8c 100644 --- a/src/asciinema/boundary/file_store.clj +++ b/src/asciinema/boundary/file_store.clj @@ -4,4 +4,5 @@ (put-file [this file path] [this file path size]) (input-stream [this path]) (move-file [this old-path new-path]) - (delete-file [this path])) + (delete-file [this path]) + (serve-file [this path opts])) diff --git a/src/asciinema/component/local_file_server.clj b/src/asciinema/component/local_file_server.clj deleted file mode 100644 index eeab31d..0000000 --- a/src/asciinema/component/local_file_server.clj +++ /dev/null @@ -1,18 +0,0 @@ -(ns asciinema.component.local-file-server - (:require [asciinema.boundary - [file-server :as file-server] - [file-store :as file-store]] - [ring.util.http-response :as response])) - -(defrecord LocalFileServer [file-store] - file-server/FileServer - (serve [this path] - (file-server/serve this path {})) - (serve [this path {:keys [filename]}] - (let [resp (response/ok (file-store/input-stream file-store path))] - (if filename - (response/header resp "Content-Disposition" (str "attachment; filename=" filename)) - resp)))) - -(defn local-file-server [{:keys [file-store]}] - (->LocalFileServer file-store)) diff --git a/src/asciinema/component/local_file_store.clj b/src/asciinema/component/local_file_store.clj index e250f1d..21823a0 100644 --- a/src/asciinema/component/local_file_store.clj +++ b/src/asciinema/component/local_file_store.clj @@ -1,25 +1,37 @@ (ns asciinema.component.local-file-store (:require [asciinema.boundary.file-store :as file-store] - [clojure.java.io :as io])) + [clojure.java.io :as io] + [ring.util.http-response :as response])) (defrecord LocalFileStore [base-path] file-store/FileStore + (put-file [this file path] (let [path (str base-path path)] (io/make-parents path) (io/copy file (io/file path)))) + (put-file [this file path size] (file-store/put-file this file path)) + (input-stream [this path] (let [path (str base-path path)] (io/input-stream path))) + (move-file [this old-path new-path] (let [old-path (str base-path old-path) new-path (str base-path new-path)] (.renameTo (io/file old-path) (io/file new-path)))) + (delete-file [this path] (let [path (str base-path path)] - (io/delete-file path)))) + (io/delete-file path))) + + (serve-file [this path {:keys [filename]}] + (let [resp (response/ok (file-store/input-stream this path))] + (if filename + (response/header resp "Content-Disposition" (str "attachment; filename=" filename)) + resp)))) (defn local-file-store [{:keys [path]}] (->LocalFileStore path)) diff --git a/src/asciinema/component/s3_file_server.clj b/src/asciinema/component/s3_file_server.clj deleted file mode 100644 index 2c04a39..0000000 --- a/src/asciinema/component/s3_file_server.clj +++ /dev/null @@ -1,37 +0,0 @@ -(ns asciinema.component.s3-file-server - (:require [asciinema.boundary.file-server :as file-server] - [clj-time - [coerce :as timec] - [core :as time]] - [ring.util.http-response :as response]) - (:import com.amazonaws.auth.BasicAWSCredentials - com.amazonaws.services.s3.AmazonS3Client - [com.amazonaws.services.s3.model GeneratePresignedUrlRequest ResponseHeaderOverrides])) - -(defn- s3-client* [cred] - (let [credentials (BasicAWSCredentials. (:access-key cred) (:secret-key cred))] - (AmazonS3Client. credentials))) - -(def ^:private s3-client (memoize s3-client*)) - -(defn- generate-presigned-url [cred bucket path {:keys [expires filename] - :or {expires (-> 1 time/days time/from-now)}}] - (let [client (s3-client cred) - request (GeneratePresignedUrlRequest. bucket path)] - (.setExpiration request (timec/to-date expires)) - (when filename - (let [header-overrides (doto (ResponseHeaderOverrides.) - (.setContentDisposition (str "attachment; filename=" filename)))] - (.setResponseHeaders request header-overrides))) - (.toString (.generatePresignedUrl client request)))) - -(defrecord S3FileServer [cred bucket path-prefix] - file-server/FileServer - (serve [this path] - (file-server/serve this path {})) - (serve [this path opts] - (let [path (str path-prefix path)] - (response/found (generate-presigned-url cred bucket path opts))))) - -(defn s3-file-server [{:keys [cred bucket path-prefix]}] - (->S3FileServer cred bucket path-prefix)) diff --git a/src/asciinema/component/s3_file_store.clj b/src/asciinema/component/s3_file_store.clj index e9fb608..4013f49 100644 --- a/src/asciinema/component/s3_file_store.clj +++ b/src/asciinema/component/s3_file_store.clj @@ -1,25 +1,58 @@ (ns asciinema.component.s3-file-store (:require [asciinema.boundary.file-store :as file-store] - [aws.sdk.s3 :as s3])) + [aws.sdk.s3 :as s3] + [clj-time + [coerce :as timec] + [core :as time]] + [ring.util.http-response :as response]) + (:import com.amazonaws.auth.BasicAWSCredentials + com.amazonaws.services.s3.AmazonS3Client + [com.amazonaws.services.s3.model GeneratePresignedUrlRequest ResponseHeaderOverrides])) + +(defn- s3-client* [cred] + (let [credentials (BasicAWSCredentials. (:access-key cred) (:secret-key cred))] + (AmazonS3Client. credentials))) + +(def ^:private s3-client (memoize s3-client*)) + +(defn- generate-presigned-url [cred bucket path {:keys [expires filename] + :or {expires (-> 1 time/days time/from-now)}}] + (let [client (s3-client cred) + request (GeneratePresignedUrlRequest. bucket path)] + (.setExpiration request (timec/to-date expires)) + (when filename + (let [header-overrides (doto (ResponseHeaderOverrides.) + (.setContentDisposition (str "attachment; filename=" filename)))] + (.setResponseHeaders request header-overrides))) + (.toString (.generatePresignedUrl client request)))) (defrecord S3FileStore [cred bucket path-prefix] file-store/FileStore + (put-file [this file path] (file-store/put-file this file path nil)) + (put-file [this file path size] (let [path (str path-prefix path)] (s3/put-object cred bucket path file {:content-length size}))) + (input-stream [this path] (let [path (str path-prefix path)] (:content (s3/get-object cred bucket path)))) + (move-file [this old-path new-path] (let [old-path (str path-prefix old-path) new-path (str path-prefix new-path)] (s3/copy-object cred bucket old-path new-path) (s3/delete-object cred bucket old-path))) + (delete-file [this path] (let [path (str path-prefix path)] - (s3/delete-object cred bucket path)))) + (s3/delete-object cred bucket path))) + + (serve-file [this path opts] + (let [path (str path-prefix path)] + (response/found (generate-presigned-url cred bucket path opts))))) (defn s3-file-store [{:keys [cred bucket path-prefix]}] (->S3FileStore cred bucket path-prefix)) diff --git a/src/asciinema/endpoint/asciicasts.clj b/src/asciinema/endpoint/asciicasts.clj index f43fd74..c1b17f2 100644 --- a/src/asciinema/endpoint/asciicasts.clj +++ b/src/asciinema/endpoint/asciicasts.clj @@ -1,7 +1,7 @@ (ns asciinema.endpoint.asciicasts (:require [asciinema.boundary [asciicast-database :as adb] - [file-server :as fserver]] + [file-store :as fstore]] [asciinema.model.asciicast :as asciicast] [compojure.api.sweet :refer :all] [ring.util.http-response :as response] @@ -10,7 +10,7 @@ (defn exception-handler [^Exception e data request] (throw e)) -(defn asciicasts-endpoint [{:keys [db file-server]}] +(defn asciicasts-endpoint [{:keys [db file-store]}] (api {:exceptions {:handlers {:compojure.api.exception/default exception-handler}}} (context @@ -21,5 +21,5 @@ (if-let [asciicast (adb/get-asciicast-by-token db token)] (let [path (asciicast/json-store-path asciicast) filename (str "asciicast-" (:id asciicast) ".json")] - (fserver/serve file-server path (when dl {:filename filename}))) + (fstore/serve-file file-store path (when dl {:filename filename}))) (response/not-found)))))) diff --git a/test/asciinema/boundary/file_server_test.clj b/test/asciinema/boundary/file_server_test.clj deleted file mode 100644 index 2136484..0000000 --- a/test/asciinema/boundary/file_server_test.clj +++ /dev/null @@ -1,7 +0,0 @@ -(ns asciinema.boundary.file-server-test - (:require [clojure.test :refer :all] - [asciinema.boundary.file-server :as file-server])) - -(deftest a-test - (testing "FIXME, I fail." - (is (= 0 1))))