fukamachi/fast-http — pull request #4 by deadtrickster (2014-10-18 09:18:39+00:00)
Title: Reset completedp, parse content length and transfer encoding when store-body is T

***Keep-alive and completedp***
`completedp` should be reset to nil immediately after it returned as T. Or all subsequent parser invocations will invoke `finish-callback` and of course return T as third value

Response:

```lisp
(let* ((response (list #?"HTTP/1.1 200 OK\r\n"
#?"Content-Length: 2 \r\n"
#?"\r\n"
#?"qw"
#?"HTTP/1.1 499 This probably should be printed once\r\n"
#?"Content-Length: 2 \r\n"
#?"\r\n"
#?"qw"))
(http (fast-http:make-http-response))
(parser (fast-http:make-parser http :finish-callback (lambda () (print http)))))
(loop for res-chunk in response do
(when (nth-value 2 (funcall parser (trivial-utf-8:string-to-utf-8-bytes res-chunk)))
(print "Message Completed!"))))

#S(FAST-HTTP.HTTP:HTTP-RESPONSE
:VERSION 11/10
:HEADERS {

}
:STORE-BODY NIL
:FORCE-STREAM NIL
:BODY NIL
:STATUS 200
:STATUS-TEXT "OK")
"Message Completed!"
#S(FAST-HTTP.HTTP:HTTP-RESPONSE
:VERSION 11/10
:HEADERS {

}
:STORE-BODY NIL
:FORCE-STREAM NIL
:BODY NIL
:STATUS 499
:STATUS-TEXT "This probably should be printed once")
"Message Completed!"
#S(FAST-HTTP.HTTP:HTTP-RESPONSE
:VERSION 11/10
:HEADERS {

}
:STORE-BODY NIL
:FORCE-STREAM NIL
:BODY NIL
:STATUS 499
:STATUS-TEXT "This probably should be printed once")
"Message Completed!"
#S(FAST-HTTP.HTTP:HTTP-RESPONSE
:VERSION 11/10
:HEADERS {

}
:STORE-BODY NIL
:FORCE-STREAM NIL
:BODY NIL
:STATUS 499
:STATUS-TEXT "This probably should be printed once")
"Message Completed!"
#S(FAST-HTTP.HTTP:HTTP-RESPONSE
:VERSION 11/10
:HEADERS {

}
:STORE-BODY NIL
:FORCE-STREAM NIL
:BODY NIL
:STATUS 499
:STATUS-TEXT "This probably should be printed once")
"Message Completed!"

```

Request:

```lisp
(let* ((request (list #?"POST / HTTP/1.1\r\n"
#?"Host: www.example.com\r\n"
#?"Content-Type: application/x-www-form-urlencoded\r\n"
#?"Content-Length: 4\r\n"
#?"\r\n"
#?"q=42\r\n"
#?"POST / HTTP/1.1\r\n"
#?"Host: www.example.com\r\n"
#?"Content-Type: application/x-www-form-urlencoded\r\n"
#?"Content-Length: 4\r\n"
#?"\r\n"
#?"q=42\r\n"))
(http (fast-http:make-http-request :store-body t ))
(parser (fast-http:make-parser http :store-body t )))
(loop for req-chunk in request do
(when (nth-value 2 (funcall parser (trivial-utf-8:string-to-utf-8-bytes req-chunk)))
(print "Message Completed!"))))

"Message Completed!"
"Message Completed!"
"Message Completed!"
"Message Completed!"
"Message Completed!"
"Message Completed!"
"Message Completed!"
"Message Completed!"
```

***:store-body t***

While exploring `completedp` problem I noticed this:

```lisp
(let* ((request (list #?"POST / HTTP/1.1\r\n"
#?"Host: www.example.com\r\n"
#?"Content-Type: application/x-www-form-urlencoded\r\n"
#?"Content-Length: 4 \r\n"
#?"\r\n"
#?"q=42\r\n"))
(http (fast-http:make-http-request :store-body t ))
(parser (fast-http:make-parser http :store-body t )))
(loop for req-chunk in request do
(when (nth-value 2 (funcall parser (trivial-utf-8:string-to-utf-8-bytes req-chunk)))
(print "Message Completed!"))))

"Message Completed!"
"Message Completed!"
```
Here we have just single request, however "Message Completed!" printed twice. Because there no callbacks, headers in highlevel parser were not parsed at all and the following `cond` clause executed and reset `completedp` to `T`:
```lisp
(T
;; No Content-Length, no chunking, probably a request with no body
(setq completedp t))
```