Unify FileStore and FileServer
parent
6943bcecca
commit
2e0cb5c3eb
@ -1,4 +0,0 @@
|
|||||||
(ns asciinema.boundary.file-server)
|
|
||||||
|
|
||||||
(defprotocol FileServer
|
|
||||||
(serve [this path] [this path opts]))
|
|
@ -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))
|
|
@ -1,25 +1,37 @@
|
|||||||
(ns asciinema.component.local-file-store
|
(ns asciinema.component.local-file-store
|
||||||
(:require [asciinema.boundary.file-store :as 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]
|
(defrecord LocalFileStore [base-path]
|
||||||
file-store/FileStore
|
file-store/FileStore
|
||||||
|
|
||||||
(put-file [this file path]
|
(put-file [this file path]
|
||||||
(let [path (str base-path path)]
|
(let [path (str base-path path)]
|
||||||
(io/make-parents path)
|
(io/make-parents path)
|
||||||
(io/copy file (io/file path))))
|
(io/copy file (io/file path))))
|
||||||
|
|
||||||
(put-file [this file path size]
|
(put-file [this file path size]
|
||||||
(file-store/put-file this file path))
|
(file-store/put-file this file path))
|
||||||
|
|
||||||
(input-stream [this path]
|
(input-stream [this path]
|
||||||
(let [path (str base-path path)]
|
(let [path (str base-path path)]
|
||||||
(io/input-stream path)))
|
(io/input-stream path)))
|
||||||
|
|
||||||
(move-file [this old-path new-path]
|
(move-file [this old-path new-path]
|
||||||
(let [old-path (str base-path old-path)
|
(let [old-path (str base-path old-path)
|
||||||
new-path (str base-path new-path)]
|
new-path (str base-path new-path)]
|
||||||
(.renameTo (io/file old-path) (io/file new-path))))
|
(.renameTo (io/file old-path) (io/file new-path))))
|
||||||
|
|
||||||
(delete-file [this path]
|
(delete-file [this path]
|
||||||
(let [path (str base-path 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]}]
|
(defn local-file-store [{:keys [path]}]
|
||||||
(->LocalFileStore path))
|
(->LocalFileStore path))
|
||||||
|
@ -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))
|
|
@ -1,25 +1,58 @@
|
|||||||
(ns asciinema.component.s3-file-store
|
(ns asciinema.component.s3-file-store
|
||||||
(:require [asciinema.boundary.file-store :as 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]
|
(defrecord S3FileStore [cred bucket path-prefix]
|
||||||
file-store/FileStore
|
file-store/FileStore
|
||||||
|
|
||||||
(put-file [this file path]
|
(put-file [this file path]
|
||||||
(file-store/put-file this file path nil))
|
(file-store/put-file this file path nil))
|
||||||
|
|
||||||
(put-file [this file path size]
|
(put-file [this file path size]
|
||||||
(let [path (str path-prefix path)]
|
(let [path (str path-prefix path)]
|
||||||
(s3/put-object cred bucket path file {:content-length size})))
|
(s3/put-object cred bucket path file {:content-length size})))
|
||||||
|
|
||||||
(input-stream [this path]
|
(input-stream [this path]
|
||||||
(let [path (str path-prefix path)]
|
(let [path (str path-prefix path)]
|
||||||
(:content (s3/get-object cred bucket path))))
|
(:content (s3/get-object cred bucket path))))
|
||||||
|
|
||||||
(move-file [this old-path new-path]
|
(move-file [this old-path new-path]
|
||||||
(let [old-path (str path-prefix old-path)
|
(let [old-path (str path-prefix old-path)
|
||||||
new-path (str path-prefix new-path)]
|
new-path (str path-prefix new-path)]
|
||||||
(s3/copy-object cred bucket old-path new-path)
|
(s3/copy-object cred bucket old-path new-path)
|
||||||
(s3/delete-object cred bucket old-path)))
|
(s3/delete-object cred bucket old-path)))
|
||||||
|
|
||||||
(delete-file [this path]
|
(delete-file [this path]
|
||||||
(let [path (str path-prefix 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]}]
|
(defn s3-file-store [{:keys [cred bucket path-prefix]}]
|
||||||
(->S3FileStore cred bucket path-prefix))
|
(->S3FileStore cred bucket path-prefix))
|
||||||
|
@ -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))))
|
|
Loading…
Reference in New Issue