I believe that `(lookahead-char port)` really blocks when the client has finished sending the request and there is no more data from `port` to consume. If I understand it correctly, then per HTTP/1.1 [1] the request ends with CRLF at the last line, and then comes the message. So I we have read an empty string, then we shouldn't proceed with further lookaheads. Specifically, the following code works out for me: (define (read-header-line port) "Read an HTTP header line, including any continuation lines, and return the combined string without its final CRLF or LF. Raise a 'bad-header' exception if the line does not end in CRLF or LF, or if EOF is reached." (format #t "Reading header line now: ") (match (%read-line port) (((? string? line) . #\newline) ;; '%read-line' does not consider #\return a delimiter; so if it's ;; there, remove it. We are more tolerant than the RFC in that we ;; tolerate LF-only endings. (let ((line (if (string-suffix? "\r" line) (string-drop-right line 1) line))) ;; If the next character is a space or tab, then there's at least ;; one continuation line. Read the continuation lines by calling ;; 'read-header-line' recursively, and append them to this header ;; line, folding the leading spaces and tabs to a single space. (if (and (not (string-null? line)) (space-or-tab? (lookahead-char port))) (string-append line " " (string-trim (read-header-line port) spaces-and-tabs)) line))) ((line . _) ;EOF or missing delimiter (bad-header 'read-header-line line)))) Moreover, the continuation lines in general have been deprecated: [2]. I have to say I would be in favor of removing support for continuation lines in general. Best regards, -Dan [1]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html [2]: https://tools.ietf.org/html/rfc7230#section-3.2.4