Commit ab452b00 authored by jan.koester's avatar jan.koester
Browse files

h1 patches

parent ad4b68cd
Loading
Loading
Loading
Loading
+33 −0
Changes for src/http.cpp: 33 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -591,6 +591,7 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe
    size_t header_end = std::string::npos;
    size_t search_from = 0;   // avoid re-scanning from 0 on every recv (O(n²) → O(n))

  read_header:
    for (;;) {
        if (raw.size() >= 4) {
            size_t start = (search_from >= 3) ? search_from - 3 : 0;
@@ -629,6 +630,18 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe
        throw he;
    }

    // RFC 9110 §15.2: 1xx interim responses (e.g. "100 Continue" answering a
    // forwarded "Expect: 100-continue") precede the real one on the same
    // connection. Taking one as final made the EOF branch below swallow the
    // real response and then block until the peer closed its keep-alive.
    // 101 is final (protocol switch) and handled by the caller.
    if (res.getStatusCode() >= 100 && res.getStatusCode() < 200 && res.getStatusCode() != 101) {
        raw.erase(raw.begin(), raw.begin() + (ptrdiff_t)parsed_hsize);
        header_end = std::string::npos;
        search_from = 0;
        goto read_header;
    }

    // Store parsed response and extract fields for redirect handling
    _lastResponse = std::make_unique<HttpResponse>(res);
    _lastStatusCode = res.getStatusCode();
@@ -653,6 +666,16 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe

    size_t body_off = parsed_hsize;

    // RFC 9112 §6.3: responses to HEAD, and 1xx/204/304 responses, never carry
    // a body regardless of Content-Length/Transfer-Encoding. Reading one anyway
    // blocked until recv timeout (Content-Length present, mirroring the GET's
    // size) or until the peer closed the keep-alive (EOF branch).
    {
        int sc = res.getStatusCode();
        if (label == "HEAD" || sc == 204 || sc == 304 || (sc >= 100 && sc < 200))
            return ret;
    }

    // 3) Determine transfer mode
    bool chunked = false;
    ptrdiff_t content_len = -1;
@@ -808,6 +831,9 @@ std::vector<char> libhttppp::HttpClient::_h1ReadResponse(const std::string &labe
            if (n == 0) break;
            ret.insert(ret.end(), _recvScratch.data.buf, _recvScratch.data.buf + n);
        }
        // The peer closed to end the body -- this socket is done; without this
        // a connection pool would hand the dead socket out again.
        _peerWantsClose = true;
    }

    return ret;
@@ -1325,6 +1351,13 @@ libhttppp::HttpResponse libhttppp::HttpClient::GetStream(libhttppp::HttpRequest
            }
        }

        // 204/304 never carry a body (RFC 9112 §6.3), whatever the headers say.
        if (res.getStatusCode() == 204 || res.getStatusCode() == 304) {
            chunked = false;
            content_len = 0;
            _streamBuf.clear();
        }

        if (chunked) {
            _streamMode = STREAM_CHUNKED;
            _streamChunkDone = false;