Обслуживание двоичных файлов из базы данных с помощью compojure - PullRequest
5 голосов
/ 21 октября 2010

У меня есть следующее определение маршрутов:

(require '[compojure.core :as ccore]
         '[ring.util.response :as response])

(def *main-routes*
     (ccore/defroutes avalanche-routes
       (ccore/GET "/" [] "Hello World 2")
       (ccore/GET "/images/:id" [id] (get-image-response id))))

В этом примере запрос / работает как брелок и возвращает ожидаемое Hello World 2.

Метод get-images-response определяется следующим образом:

(defn get-image-response
  [id]
  (let [record (db/get-image id false)]
    (-> (response/response (:data record))
        (response/content-type (:content-type record))
        (response/header "Content-Length" (:size record)))))

Я получаю 404, так что подача двоичных файлов еще не совсем работает. Есть идеи почему?

Edit: Хорошо, проблема связана с тем, что изображения запрашиваются на /images/name.jpg. Как только я удаляю .jpg, вызывается обработчик. Поэтому возникает вопрос: как мне сопоставить что-либо, кроме расширения?

Ответы [ 2 ]

11 голосов
/ 21 октября 2010

Compojure использует clout для сопоставления маршрута. Точечный символ имеет особое значение в маршрутах. Он представляет разделитель токенов, аналогично символу косой черты. Следующие символы имеют это значение в clout: / . , ; ?.

Это означает, что маршрут типа "/images/:id" не будет соответствовать uri вида /images/name.jpg, поскольку images, name и jpg каждый представляет отдельный токен в clout.

Чтобы сопоставить его, вы можете составить маршрут различными способами, в зависимости от ваших потребностей.

Если все ваши изображения имеют расширение .jpg, проще всего будет:

(GET "/images/:id.jpg" [id] ...)

Если расширение варьируется, вы можете сделать следующее:

(GET "/images/:name.:extension" [name extension] ...)

Если вы хотите ограничить расширение, вы можете передать compojure / clout регулярное выражение:

(GET ["/images/:name.:ext", :ext #"(jpe?g|png|gif)"] [name ext] ...)

Вы также можете использовать подстановочный знак, который является менее точным и будет соответствовать любому URI, начинающемуся с /images/:

(GET "/images/*" [*] ...)
4 голосов
/ 22 октября 2010

Реальным ответом в этом случае было то, что была ошибка в библиотеке clojure-couchdb. Патч доступен на github здесь .

Все сводится к добавлению параметра и значения карты {: as: byte-array} к запросу, отправляемому через clj-http, в файл API.

Другая проблема в моем коде заключалась в том, что ring не знает, что делать с байтовыми массивами при их рендеринге. Вместо того, чтобы исправлять кольцо, я просто поместил байтовый массив в java.io.ByteArrayInputStream. Вот полный код для обработки загрузки:

(defn get-image-response
  [id]
  (let [record (db/get-image id false)]
    (-> (response/response (new java.io.ByteArrayInputStream (:data record)))
        (response/content-type (:content-type (:content-type record)))
        (response/header "Content-Length" (:size record)))))
...