-
-
Save Hendekagon/7ab2c5c706dde70268f030c07550abe5 to your computer and use it in GitHub Desktop.
add 206 partial content in Aleph
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; ---- the following fns copied from ring.util.response because they were | |
; useful but private ---- | |
(defn canonical-path [^File file] | |
(str (.getCanonicalPath file) | |
(if (.isDirectory file) File/separatorChar))) | |
(defn safe-path? [^String root ^String path] | |
(.startsWith (canonical-path (File. root path)) | |
(canonical-path (File. root)))) | |
(defn directory-transversal? | |
"Check if a path contains '..'." | |
[^String path] | |
(-> (str/split path #"/|\\") | |
(set) | |
(contains? ".."))) | |
(defn find-file-named [^File dir ^String filename] | |
(let [path (File. dir filename)] | |
(if (.isFile path) | |
path))) | |
(defn find-file-starting-with [^File dir ^String prefix] | |
(first | |
(filter | |
#(.startsWith (.toLowerCase (.getName ^File %)) prefix) | |
(.listFiles dir)))) | |
(defn find-index-file | |
"Search the directory for an index file." | |
[^File dir] | |
(or (find-file-named dir "index.html") | |
(find-file-named dir "index.htm") | |
(find-file-starting-with dir "index."))) | |
(defn safely-find-file [^String path opts] | |
(if-let [^String root (:root opts)] | |
(if (or (safe-path? root path) | |
(and (:allow-symlinks? opts) (not (directory-transversal? path)))) | |
(File. root path)) | |
(File. path))) | |
(defn find-file [^String path opts] | |
(if-let [^File file (safely-find-file path opts)] | |
(cond | |
(.isDirectory file) | |
(and (:index-files? opts true) (find-index-file file)) | |
(.exists file) | |
file))) | |
(defn content-length [resp len] | |
(if len | |
(rr/header resp "Content-Length" len) | |
resp)) | |
; ---- handle 206 partial content requests | |
(defn partial-file-data [^File file from lenth] | |
(info " partial file:" from lenth) | |
(let [ | |
f (RandomAccessFile. file "r") | |
c (.getChannel f) | |
b (.map c FileChannel$MapMode/READ_ONLY from lenth) | |
] | |
(try | |
(bs/to-byte-array b) | |
(finally (.close c))))) | |
; "bytes=500-999" | |
(defn parse-range [s] | |
(debug "parse range " s) | |
(let [[_ & s] (string/split s #"=|-")] | |
(map (fn [s] (Long/parseLong s)) s))) | |
(defn partial-file-response | |
[root {{uuid :uuid pfrom :from pto :to} :params :as req}] | |
(debug (str "partial file request " root req)) | |
(let [filepath (str root uuid) opts nil] | |
(if-let [file (find-file filepath opts)] | |
(let [ | |
total-length (.length file) | |
range-str (get-in req [:headers "Range"]) | |
[from to] | |
(if range-str | |
(parse-range range-str) | |
(if (and pfrom pto) | |
(map (fn [s] (Long/parseLong s)) [pfrom pto]) | |
[0 total-length])) | |
to (min (or to total-length) total-length) | |
from (max 0 (or from 0)) | |
lenth (- to from) | |
] | |
(debug "206 range" from to lenth ) | |
(if (> to from) | |
(let [data (partial-file-data file from lenth)] | |
{:status 206 | |
:headers | |
{ | |
"Content-Length" lenth | |
"Content-Range" (str "bytes " from "-" to "/" total-length) | |
} | |
:body data}) | |
{:status 400 :body "invalid range"}))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment