diff --git a/httplib.h b/httplib.h index 08ce930..6e12e3a 100644 --- a/httplib.h +++ b/httplib.h @@ -1114,6 +1114,11 @@ public: } } + bool end_with_crlf() const { + auto end = ptr() + size(); + return size() >= 2 && end[-2] == '\r' && end[-1] == '\n'; + } + bool getline() { fixed_buffer_used_size_ = 0; glowable_buffer_.clear(); @@ -1562,34 +1567,33 @@ inline uint64_t get_header_value_uint64(const Headers &headers, const char *key, } inline bool read_headers(Stream &strm, Headers &headers) { - // Horizontal tab and ' ' are considered whitespace and are ignored when on - // the left or right side of the header value: - // - https://stackoverflow.com/questions/50179659/ - // - https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html - static std::regex re(R"((.+?):[\t ]*(.+))"); - const auto bufsiz = 2048; char buf[bufsiz]; - stream_line_reader line_reader(strm, buf, bufsiz); for (;;) { if (!line_reader.getline()) { return false; } - const char *end = line_reader.ptr() + line_reader.size(); - auto erase_last_char = [&](char c) { - if (line_reader.ptr() == end || end[-1] != c) { - return false; - } + + // Check if the line ends with CRLF. + if (line_reader.end_with_crlf()) { + // Blank line indicates end of headers. + if (line_reader.size() == 2) { break; } + } else { + continue; // Skip invalid line. + } + + // Skip trailing spaces and tabs. + auto end = line_reader.ptr() + line_reader.size() - 2; + while (line_reader.ptr() < end && (end[-1] == ' ' || end[-1] == '\t')) { end--; - return true; - }; - if (!erase_last_char('\n')) { continue; } - if (!erase_last_char('\r')) { continue; } + } - // Blank line indicates end of headers. - if (line_reader.ptr() == end) { break; } + // Horizontal tab and ' ' are considered whitespace and are ignored when on + // the left or right side of the header value: + // - https://stackoverflow.com/questions/50179659/ + // - https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html + static const std::regex re(R"((.+?):[\t ]*(.+))"); - while (erase_last_char(' ') || erase_last_char('\t')) {} std::cmatch m; if (std::regex_match(line_reader.ptr(), end, m, re)) { auto key = std::string(m[1]);