我正在使用Common Lisp编写一个最小的Web服务器,并希望它能够具备一些基本的静态文件服务能力。这个想法是用于开发,测试和其他低流量情况,因此它不必特别有效。它也不必处理大文件。但是,它必须工作,并且在尝试提供图像时出现此错误:
...
(with-open-file (s path :direction :input :element-type 'octet)
(let ((buf (make-array (file-length s) :element-type 'octet)))
(read-sequence buf s)
(write! (make-instance
'response :content-type mime
:body buf)
sock))
(socket-close sock))
...
具体来说,它给了我错误
The value 137 is not of type CHARACTER.
[Condition of type TYPE-ERROR]
...
write!
的相关部分看起来像
...
(write-string "Content-Length: " stream) (write (length body) :stream stream) (crlf stream)
(crlf stream)
(write-sequence body stream)
(crlf stream)
...
我尝试将其更改为
...
(write-string "Content-Length: " stream) (write (length body) :stream stream) (crlf stream)
(crlf stream)
(write-string (flexi-streams:octets-to-string body) stream)
(crlf stream)
...
然后错误消失,但客户端获得该文件的错误版本。您可以在上面的代码here周围看到更多上下文。
我做错了什么?
系统构建于:usocket
之上,:flexi-streams
用于octet
。以上是对Hunchentoot采用了一种非常类似的方法(参见静态文件片段here;该代码在事先进行分块和其他一些检查,但在其他方面似乎做了同样的事情)。我正在运行:quicklisp
中的最新内容,并在64位Debian stable上运行SBCL 1.0.57.0.debian
。
答案 0 :(得分:1)
感谢来自jasom
的{{1}}和Bike
作为答案:
如果要从基于#lisp
的服务器提供静态文件,则需要
usocket
第一点很容易。请致电flexi-streams
,或将(ql:quickload :flexi-streams)
添加到#:flexi-streams
的{{1}}行。
第二点涉及使用附加参数调用:depends-on
:
.asd
第三,你不需要绕过套接字并在任何地方写socket-accept
,而是需要进行(socket-accept ready :element-type 'octet)
调用。
(socket-stream socket)
根据您的具体情况,将上述每次写入/读取包装起来或者执行一次(在您致电make-flexi-stream
之后)然后将(let ((stream (flex:make-flexi-stream (socket-stream sock) :external-format :utf-8)))
;;; stuff you want to do
)
与套接字。