http - 使用 Clack/ningle 在 Web 服务器中嵌入图像

我正在使用 Common Lisp 开发一个小型网络服务器,但是我在包含像 png 这样的二进制数据时遇到了问题。为了读取 png 等静态文件,我创建了一个宏,它会根据用户指定的文件类型添加新的 Ningle 路由。这包括一个读取器函数参数,该参数将从文件名创建数据。它适用于基于文本的文件,如 css、html、js(text/css、text/html、text/js 等)。

如何让 Ningle 读取二进制数据作为内容?

这是我的代码

(defun read-file (&key (filename "index.html"))
  (let
      ((in (open filename :if-does-not-exist nil))
       (out ""))
    (when in
      (loop for line = (read-line in nil)
            while line do
              (progn
                (setf out (concatenate 'string out (format nil "~a~%" line)))))
      (close in)
      out)))

(defun make-adjustable-string (s)
               (make-array (length s)
                           :fill-pointer (length s)
                           :adjustable t
                           :initial-contents s
                           :element-type (array-element-type s)))

(defun read-binary (&key (filename "img/free.png"))
  (let
      ((in (open filename :if-does-not-exist nil :external-format :unix :element-type '(unsigned-byte 8)))
       (out ""))
    (when in
      (loop for byte = (read-byte in nil)
            while byte do
              (progn
                (setf out (make-adjustable-string out))
                (vector-push-extend (code-char byte) out)))
      (close in)
      out)))

(defmacro add-static-file-handler (filetype &key (html-type (concatenate 'string "text/" filetype)) (reader-function #'read-file))
  (setf (ningle:route *app* (concatenate 'string "*/:file." filetype))
        #'(lambda (params)
            (let*
                ((path (car (cdr (assoc :splat params))))
                 (filename (concatenate 'string path "/" (cdr (assoc :file params)) (concatenate 'string "." filetype)))
                 (file (funcall reader-function :filename (concatenate 'string "." filename))))
              (cond
                (file (list 200 (list :content-type html-type) (list file)))
                (t (list 404 '(:content-type "text/html") (list (concatenate 'string filename " could not be found")))))))))
                                     
(add-static-file-handler "css")
(add-static-file-handler "html")
(add-static-file-handler "js")
(add-static-file-handler "txt" :html-type "text/plain" )

(add-static-file-handler "png" :html-type "image/png" :reader-function read-binary)

首先,这真的很慢。必须有一个更快的方法。 其次,举个例子,当我向它扔一个 10x10 png 时,它会出现:

PNG

IHDR

2ϽdêIDAT]1KÃpÄWP·BAppt.D\\ÅUprܳº8º%ÃÐÉID5! ADdÃ?­©Ç»w¼{$¼·+»\\·
                                                                 ÙåÓ45°èA$ÉowvNù»:Ë2×uDZ={
                                                                                          ×zbç²
ëÁÉ¡(¦i8»:9t\\ÈI¸^%y{$ß\\˱Y<û2ÝX÷!É0ØG3Ú'?óðÖ çaV3Âí=ìIü©»â[IEND®B`

这似乎是正确的。我的意思是它看起来像一个二进制文件。但是,在浏览器上查看时,它只是默认的损坏图像图标。

最佳答案

最简单的方法就是让 Ningle 有机会处理所有事情。只需从处理程序返回一个路径名:

CL-USER> (defvar *app* (make-instance 'ningle:app))
*APP*

CL-USER> (setf (ningle:route *app* "/some.png")
               #P"/Users/art/Downloads/demo.png")
#P"/Users/art/Downloads/demo.png"

CL-USER> (clack:clackup *app*)
Hunchentoot server is started.
Listening on 127.0.0.1:5000.
#S(CLACK.HANDLER::HANDLER
   :SERVER :HUNCHENTOOT
   :ACCEPTOR #<SB-THREAD:THREAD "clack-handler-hunchentoot" RUNNING
                {1017FC2433}>)

Ningle 将完成剩下的工作:

$ curl -v http://localhost:5000/some.png
* Connected to localhost (127.0.0.1) port 5000 (#0)
> GET /some.png HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 06 May 2021 20:35:59 GMT
< Server: Hunchentoot 1.3.0
< Content-Length: 50661
< Accept-Ranges: bytes
< Last-Modified: Mon, 19 Apr 2021 08:53:21 GMT
< Content-Type: image/png
<
Warning: Binary output can mess up your terminal

https://stackoverflow.com/questions/67363570/

相关文章:

flutter - 为什么 SliverFillRemaining 膨胀得太多了?

python - 仅当 "Lossless"时才转换为整数?

javascript - 选择选项后如何取消突出显示选择元素?

GitHub - 当非默认分支与 main 合并时,PR 链接问题不会关闭

python - PyCharm 看不到项目中的文件

matlab - 如何使用 matlab 正确绘制矢量线性方程?

git - 如何在 GIT 中查看暂存区中的文件内容?

c++ - 使用具有非 constexpr 值的 int 模板函数

powerbi - Multi-Tenancy 场景下如何访问power BI Service

r - 将字符串拆分为单词并分配给新列