rewrite http-read-line of http://d.hatena.ne.jp/shammer/20160320/p1
In the article Lisp HTTP Client handling chunked responses - Shammerism, I wrote a HTTP client which can handle chunked response. In this article, the function whose name is http-read-line uses do loop, but I would like to rewrite as recursive. Here is a re-write version.
(define-condition invalid-http-line-error (error) ((text :initarg :text :reader get-error-message)) (:report (lambda (condition stream) (format stream "~S.~%" (get-error-message condition))))) (defun read-http-line-as-bytes () (let ((c (read-byte *client-stream* nil 'eof))) (cond ((equal c 'eof) (error (make-condition 'invalid-http-line-error :text "Client closed socket during read-http-line"))) ((equal c 13) (let ((next (read-byte *client-stream* nil 'eof))) (if (equal next 10) (list 13 10) (error (make-condition 'invalid-http-line-error :text "Invalid http line, http line should be finished with 13 10"))))) (t (append (list c) (flatten (list (read-http-line-as-bytes)))))))) (defun read-http-line-as-string () (labels ((close-socket-after-message-output (message) (format t "~A~%" message) (close *client-stream*))) (handler-case (let ((byte-list (read-http-line-as-bytes))) (if (equal byte-list (list 13 10)) "" (decode-string-from-octets (coerce (subseq byte-list 0 (- (length byte-list) 2)) ;; Remove (13 10) before convert to string '(simple-array (unsigned-byte 8))) :external-format :utf-8))) (invalid-http-line-error (ihle) (close-socket-after-message-output (format nil "Invalid HTTP line received with ~A, close this connection.~%" (get-error-message ihle)))))))
I used adjustable array whose element type is unsigned-byte 8 with the following function, but I found the way how to do the same thins as this function with only lisp standard libraries.
(defun make-byte-array () (make-array 0 :fill-pointer 0 :adjustable t :element-type '(unsigned-byte 8)))
Using coerce with following options can do the same thing.
? (coerce list '(simple-array (unsigned-byte 8)))
There are a lot of things to learn about lisp. I keep learning Lisp to be able to use Lisp as well as Java. I wrote a lot of code, but there are a lot of wasted code, I guess. I have to brush up my Lisp code.