如何配置Common Lisp(usocket)服务器使Firefox渲染HTML?
问题描述
参考《Land Of Lisp》第12章内容,用SBCL结合usocket包编写了本地服务器,代码运行后通过浏览器访问http://127.0.0.1:4123/时,页面仅显示HTML源码而非渲染后的内容。经确认,问题出在缺少HTTP响应头中的Content-Type: text/html配置。
解决方案
usocket是底层套接字操作库,不处理HTTP协议的封装逻辑,因此需要手动构造完整的HTTP响应内容,包含状态行、响应头(指定Content-Type),再发送HTML正文。
HTTP响应的基本格式要求:
- 状态行(如
HTTP/1.1 200 OK) - 若干响应头字段(每行一个,格式为
键: 值) - 一个空行(分隔响应头和正文)
- 响应正文(HTML内容)
修改后的代码
#!/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*)) ;; 读取客户端的HTTP请求行 (loop for line = (read-line *my-stream* nil nil) while line do (format t "~a~%" line)) (force-output) ;; 发送完整的HTTP响应 (format *my-stream* "HTTP/1.1 200 OK~%") (format *my-stream* "Content-Type: text/html; charset=utf-8~%") (let ((html-content "<html><body>Server will write something exciting here.</body></html>")) (format *my-stream* "Content-Length: ~a~%~%" (length html-content)) (format *my-stream* "~a" html-content)) (force-output *my-stream*)) ;; call communication and close socket, no matter what (unwind-protect (communi) (format t "Closing socket connection...~%") (when *sock-listen* (usocket:socket-close *sock-listen*)) (when *sock* (usocket:socket-close *sock*)))
关键修改说明
- 新增HTTP状态行
HTTP/1.1 200 OK,告知客户端请求处理成功 - 添加
Content-Type: text/html; charset=utf-8响应头,明确告诉浏览器内容为HTML格式 - 补充
Content-Length头,指定正文长度,让浏览器可以正确接收并渲染内容 - 将原代码中仅读取单个S表达式的逻辑,改为循环读取所有请求行,避免程序因HTTP请求格式导致阻塞
内容的提问来源于stack exchange,提问作者Dominik Mokriš
相关产品推荐
相关产品推荐

