我的目标类似于 Land Of Lisp 的第 12 章:在 SBCL 中使用 usocket 包,我想编写一个可以使用浏览器连接的本地服务器。我从一个有用的例子开始:
#!/usr/bin/sbcl --script
(load "~/quicklisp/setup.lisp")
(require :usocket)
(defparameter *sock* nil)
(defparameter *sock-listen* nil)
(defparameter *my-stream* nil)
(defun communi ()
;; bind socket
(setf *sock* (usocket:socket-listen "127.0.0.1" 4123))
;; listen to incoming connections
(setf *sock-listen* (usocket:socket-accept *sock* :element-type 'character))
; open stream for communication
(setf *my-stream* (usocket:socket-stream *sock-listen*))
;; print message from client
(format t "~a~%" (read *my-stream*))
(force-output)
;; send answer to client
(format *my-stream* "<html><body>Server will write something exciting here.</body></html>")
(force-output *my-stream*))
;; call communication and close socket, no matter what
(unwind-protect (communi)
(format t "Closing socket connection...~%")
(usocket:socket-close *sock-listen*)
(usocket:socket-close *sock*))
当我从命令行(Ubuntu 22.04 LTS)运行此脚本时,我可以使用 Firefox 连接到
http://127.0.0.1:4123/
。但是,Firefox 不呈现 HTML,而是仅显示其源代码:
<html><body>Server will write something exciting here.</body></html>
问题: 如何说服 Firefox 渲染页面而不是显示 HTML 源代码?
text/html
。 curl
输出证实了这一点
dominik@computer:~$ curl 127.0.0.1:4123 --http0.9 --verbose
* Trying 127.0.0.1:4123...
* Connected to 127.0.0.1 (127.0.0.1) port 4123 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:4123
> User-Agent: curl/8.1.2
> Accept: */*
>
* Closing connection 0
<html><body>Server will write something exciting here.</body></html>
与
明显不同dominik@computer:~$ curl example.com -I
HTTP/1.1 200 OK
Accept-Ranges: bytes
Age: 256982
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Sun, 26 May 2024 18:05:14 GMT
Etag: "3147526947"
Expires: Sun, 02 Jun 2024 18:05:14 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECAcc (dcd/7D7F)
X-Cache: HIT
Content-Length: 1256
如何设置
usocket包中的
content-type
?
由于您要实现的服务器应该是 http 服务器,因此您需要提供响应标头,然后在有效负载之前提供一个空行。例如。
(let ((content "<html><body>Server will write something exciting here.</body></html>"))
(format *my-stream*
"HTTP/1.1 200 OK~%~&~
content-type: text/html~%~&~
content-length: ~D~%~&~
~%~&~
~a"
(length content)
content))
这将根据 http 规范输出标头和使用 CRLF 作为行分隔符的空行,然后是有效负载。