(in-package #:http) (defgeneric $connected (stream)) (defmethod $connected ((*stream* sb-sys:fd-stream) &aux (buffer (make-array 8192 :element-type '(unsigned-byte 8))) (length (read-sequence buffer *stream*)) ( (flexi-streams:octets-to-string (subseq buffer 0 length)))) ($output "Connected...~A~%Headers: ~%~A" *standard-output* ) (let* ((element-type '(unsigned-byte 8)) (buffer (make-array 8192 :element-type element-type))) (with-open-file (in "~/celwk/static/favicon.ico" :element-type element-type) (write-sequence (fmt "HTTP/1.1 200 OK~%~ Connection: keep-alive~%~ Access-Control-Allow-Origin: *~%~ Accept-Ranges: bytes: ~%~ When: ~A~%~ Content-Type: image/x-icon~%~ Content-Length: ~A~% " (now) (file-length in)) *stream* :end 40) (force-output *stream*) ($output "Wait...") (sleep 3) (loop (let ((position (read-sequence buffer in))) (vprint position) (when (zerop position) (return)) (write-sequence buffer *stream* :end position) (force-output *stream*)))))) (do ((line (trim (read-sequence buffer *stream* nil "")) (trim (read-line *stream* nil "")))) ((string= line "")) (push line )) (unless ($output "Over") (return-from $connected)) (destructuring-bind (method path protocal) (split #"\s+"# (last1 )) (format *error-output* "~%Method: ~A~%Protocal: ~A~%Headers: ~A~%" method protocal ) (cond ((string= path "/favicon.ico") (write-file path)) (:otherwise (write-string (@content-of path) *stream*))) (force-output *stream*)) ;; (vprint (open-stream-p *stream*)) ($connected *stream*)) (defun write-file (path) (setf path (concat "~/celwk/static" path)) (vprint path) (let* ((element-type '(unsigned-byte 8)) (buffer (make-array 8192 :element-type element-type))) (with-open-file (in path :element-type element-type) (write-string (fmt "HTTP/1.1 200 OK~%~ Connection: keep-alive~%~ Access-Control-Allow-Origin: *~%~ Accept-Ranges: bytes: ~%~ When: ~A~%~ Content-Type: image/x-icon~%~ Content-Length: ~A~% " (now) (file-length in)) *stream*) (force-output *stream*) (loop (let ((position (read-sequence buffer in))) (vprint position) (when (zerop position) (return)) (write-sequence buffer *stream* :end position)))))) (defun start-server (&optional (port *port*)) (setf *server* (make-instance 'inet-socket :type :stream :protocol :tcp) *clients* nil *port* port (sockopt-reuse-address *server*) t) ;; (setf (non-blocking-mode *server*) t) (socket-bind *server* *address* *port*) (socket-listen *server* *backlog*) (format t "~&Listening :~A~%" port) (make-thread ; For continue REPL λ(loop (multiple-value-bind (inet-socket peer) (socket-accept *server*) (let ((*stream* (socket-make-stream inet-socket :input t :output t :element-type '(unsigned-byte 8)))) ($output "[[ Stream Coming::~A ]]~%" peer) (push *standard-output* *clients*) (make-thread #'$connected :arguments (list *stream*)))))))