Implement parsing for image/jpeg responses

This commit is contained in:
heyarne 2020-08-22 10:56:55 +02:00
commit e5e97e14e0

View file

@ -14,8 +14,13 @@
(defn fetch-url [url]
(future (html/html-snippet (:body (http/get url)))))
;; here are some hand-picked webcams:
;; colorado springs: https://www.insecam.org/en/view/481423/
;; salzburg: https://www.insecam.org/en/view/540433/
;; not madrid: https://www.insecam.org/en/view/856408/
(def some-detail-page
@(fetch-url "https://www.insecam.org/en/view/540433/"))
@(fetch-url "https://www.insecam.org/en/view/856408/"))
(def some-camera-image
(->
@ -36,12 +41,7 @@
;; we're only interested in the first chunk of data, so we need to figure out
;; how we can close the connection afterwards and discard the other ones.
;; TODO: To read the image the following is done
;; - Find the first boundary
;; - Load all following bytes into a buffer until the buffer appears the next time
;; - Return the buffer
;; NOTE A more elegant method might be this:
;; Our approach is this:
;; - Convert the stream into a lazy sequence of bytes
;; - Partition the lazy sequence whenever you find (str "--" boundary)
;; - Select the part of the sequence you want
@ -83,12 +83,9 @@
{:header (apply str (map char (first parsed)))
:body (byte-array (apply concat (rest parsed)))}))
(defn parse-multipart [request]
(defn parse-mixed-replace [request]
(let [content-type (get-in request [:headers "Content-Type"])
boundary (str "--" (second (re-find #"boundary=\"(.*?)\"" content-type)) "\r\n")]
;; let's throw in an assert because we have no idea how other servers
;; implement streaming or wether they implement it at all
(assert (some? boundary) "Could not parse multipart/x-mixed-replace boundary")
boundary (str "--" (second (re-find #"boundary=(?:\")?(.*?)(?:\")?(;|$)" content-type)) "\r\n")]
(with-open [input (:body request)]
;; find indices of the bytes between the first and second boundary; the byte
;; sequence always starts with the boundary, which is why can skip the first
@ -99,7 +96,26 @@
;; first (empty) split
(parse-multipart-alternative (second (partition-with-seq boundary-seq byte-seq)))))))
(def first-multipart-chunk (parse-multipart (http/get some-camera-image {:as :stream})))
(defn parse-image [request]
(with-open [input (:body request)]
(byte-array (input->byte-seq input))))
(defmulti parse-response-body (fn [req]
(second (re-find #"^(.*?)(;|$)" (get-in req [:headers "Content-Type"])))))
(defmethod parse-response-body "multipart/x-mixed-replace" [req]
(:body (parse-mixed-replace req)))
(defmethod parse-response-body "image/jpeg" [req]
(parse-image req))
#_(ns-unmap *ns* 'parse-response-body)
(defmethod parse-response-body :default [req]
(throw (IllegalArgumentException.
(str "No parser defined for content-type " (pr-str (get-in req [:headers "Content-Type"]))))))
(def webcam-picture (parse-response-body (http/get some-camera-image {:as :stream})))
;; we need javax to convert the byte array that is contained in the body of the
;; first multipart alternative to a `BufferedImage` that we can use