🐛 Validate HTTP status code when downloading image from URL

Raise a :validation error with :unable-to-download-from-url code when
the remote URL returns a non-2xx HTTP status, so callers receive an
explicit error instead of a silent success with missing media data.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
Andrey Antukh
2026-03-09 16:55:08 +00:00
parent ab6faa2c0a
commit addc2c701b
2 changed files with 29 additions and 1 deletions

View File

@@ -298,12 +298,18 @@
(defn download-image
"Download an image from the provided URI and return the media input object"
[{:keys [::http/client]} uri]
(letfn [(parse-and-validate [{:keys [headers] :as response}]
(letfn [(parse-and-validate [{:keys [headers status] :as response}]
(let [size (some-> (get headers "content-length") d/parse-integer)
mtype (get headers "content-type")
format (cm/mtype->format mtype)
max-size (cf/get :media-max-file-size default-max-file-size)]
(when-not (and (>= status 200) (< status 300))
(ex/raise :type :validation
:code :unable-to-download-from-url
:hint "the url returned a non-success http status"
:http-status status))
(when-not size
(ex/raise :type :validation
:code :unknown-size

View File

@@ -270,6 +270,28 @@
(t/is (= :validation (:type error-data)))
(t/is (= :unable-to-access-to-url (:code error-data))))))
(t/deftest media-object-from-url-command-when-url-returns-error-status
(let [prof (th/create-profile* 1)
proj (th/create-project* 1 {:profile-id (:id prof)
:team-id (:default-team-id prof)})
file (th/create-file* 1 {:profile-id (:id prof)
:project-id (:default-project-id prof)
:is-shared false})
;; Use a URL that reliably returns a 404 non-success status
url "https://raw.githubusercontent.com/uxbox/uxbox/develop/sample_media/images/unsplash/this-image-does-not-exist.jpg"
params {::th/type :create-file-media-object-from-url
::rpc/profile-id (:id prof)
:file-id (:id file)
:is-local true
:url url}
out (th/command! params)]
(let [error (:error out)
error-data (ex-data error)]
(t/is (th/ex-info? error))
(t/is (= :validation (:type error-data)))
(t/is (= :unable-to-download-from-url (:code error-data))))))
(t/deftest media-object-upload-command-when-file-is-deleted
(let [prof (th/create-profile* 1)
proj (th/create-project* 1 {:profile-id (:id prof)