Loading src/http.cpp +45 −19 Original line number Diff line number Diff line Loading @@ -787,6 +787,7 @@ libhttppp::HttpResponse libhttppp::HttpClient::GetStream(libhttppp::HttpRequest _streamH3EndStream = false; _streamH3Raw.clear(); _streamH3Body.clear(); _streamH3BodyPos = 0; _streamH3InDataFrame = false; _streamH3DataRemaining = 0; Loading Loading @@ -1515,11 +1516,15 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { // ── HTTP/3 streaming mode ── if (_streamMode == STREAM_H3) { // First drain any body data buffered during GetStream / previous reads if (!_streamH3Body.empty()) { size_t have = _streamH3Body.size(); if (_streamH3BodyPos < _streamH3Body.size()) { size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -1553,7 +1558,7 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { // to think the stream is done. auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(60); while (_streamH3Body.empty()) { while (_streamH3BodyPos >= _streamH3Body.size()) { // Drain all available stream data { uint8_t rbuf[65536]; Loading Loading @@ -1635,7 +1640,8 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { _streamH3Raw.erase(_streamH3Raw.begin(), _streamH3Raw.begin() + static_cast<ptrdiff_t>(pos)); // Check stream completion if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3Body.empty() if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3BodyPos >= _streamH3Body.size() && !_streamH3InDataFrame && !q->hasStreamData(_streamH3Sid)) { _streamH3EndStream = true; _streamMode = STREAM_NONE; Loading @@ -1644,10 +1650,14 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { } // Return decoded body data size_t have = _streamH3Body.size(); size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -1714,11 +1724,15 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize // ── HTTP/3 non-blocking streaming ── if (_streamMode == STREAM_H3) { // Drain already-decoded body data first if (!_streamH3Body.empty()) { size_t have = _streamH3Body.size(); if (_streamH3BodyPos < _streamH3Body.size()) { size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -1755,7 +1769,8 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize } if (!got_any && _streamH3Raw.empty() && !_streamH3InDataFrame) { if (q->isStreamComplete(_streamH3Sid) && !q->hasStreamData(_streamH3Sid)) { && !q->hasStreamData(_streamH3Sid) && _streamH3BodyPos >= _streamH3Body.size()) { _streamH3EndStream = true; _streamMode = STREAM_NONE; return static_cast<size_t>(-1); Loading Loading @@ -1808,15 +1823,20 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize if (pos > 0) _streamH3Raw.erase(_streamH3Raw.begin(), _streamH3Raw.begin() + static_cast<ptrdiff_t>(pos)); if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3Body.empty() if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3BodyPos >= _streamH3Body.size() && !_streamH3InDataFrame && !q->hasStreamData(_streamH3Sid)) _streamH3EndStream = true; if (!_streamH3Body.empty()) { size_t have = _streamH3Body.size(); if (_streamH3BodyPos < _streamH3Body.size()) { size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -4322,6 +4342,12 @@ void libhttppp::HttpRequest::setRequestURL(const std::string &url){ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ // Clear previous results so re-parsing doesn't duplicate entries _multipartEntries.clear(); _urlEntries.clear(); _boundary.clear(); _contentType.clear(); if(request.getRequestType()==POSTREQUEST || request.getRequestType()==PUTREQUEST){ HttpHeader::HeaderData *ctype=request.getHeaderData("content-type"); Loading src/http.h +1 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ namespace libhttppp { bool _streamH3EndStream = false; std::vector<uint8_t> _streamH3Raw; // raw frame buffer std::vector<char> _streamH3Body; // decoded DATA frames not yet consumed size_t _streamH3BodyPos = 0; // consumed offset into _streamH3Body bool _streamH3InDataFrame = false; // true when inside a partial DATA frame uint64_t _streamH3DataRemaining = 0; // bytes left in current DATA frame Loading Loading
src/http.cpp +45 −19 Original line number Diff line number Diff line Loading @@ -787,6 +787,7 @@ libhttppp::HttpResponse libhttppp::HttpClient::GetStream(libhttppp::HttpRequest _streamH3EndStream = false; _streamH3Raw.clear(); _streamH3Body.clear(); _streamH3BodyPos = 0; _streamH3InDataFrame = false; _streamH3DataRemaining = 0; Loading Loading @@ -1515,11 +1516,15 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { // ── HTTP/3 streaming mode ── if (_streamMode == STREAM_H3) { // First drain any body data buffered during GetStream / previous reads if (!_streamH3Body.empty()) { size_t have = _streamH3Body.size(); if (_streamH3BodyPos < _streamH3Body.size()) { size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -1553,7 +1558,7 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { // to think the stream is done. auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(60); while (_streamH3Body.empty()) { while (_streamH3BodyPos >= _streamH3Body.size()) { // Drain all available stream data { uint8_t rbuf[65536]; Loading Loading @@ -1635,7 +1640,8 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { _streamH3Raw.erase(_streamH3Raw.begin(), _streamH3Raw.begin() + static_cast<ptrdiff_t>(pos)); // Check stream completion if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3Body.empty() if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3BodyPos >= _streamH3Body.size() && !_streamH3InDataFrame && !q->hasStreamData(_streamH3Sid)) { _streamH3EndStream = true; _streamMode = STREAM_NONE; Loading @@ -1644,10 +1650,14 @@ size_t libhttppp::HttpClient::readBodyChunk(char *buf, size_t bufsize) { } // Return decoded body data size_t have = _streamH3Body.size(); size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -1714,11 +1724,15 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize // ── HTTP/3 non-blocking streaming ── if (_streamMode == STREAM_H3) { // Drain already-decoded body data first if (!_streamH3Body.empty()) { size_t have = _streamH3Body.size(); if (_streamH3BodyPos < _streamH3Body.size()) { size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -1755,7 +1769,8 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize } if (!got_any && _streamH3Raw.empty() && !_streamH3InDataFrame) { if (q->isStreamComplete(_streamH3Sid) && !q->hasStreamData(_streamH3Sid)) { && !q->hasStreamData(_streamH3Sid) && _streamH3BodyPos >= _streamH3Body.size()) { _streamH3EndStream = true; _streamMode = STREAM_NONE; return static_cast<size_t>(-1); Loading Loading @@ -1808,15 +1823,20 @@ size_t libhttppp::HttpClient::readBodyChunkNonBlocking(char *buf, size_t bufsize if (pos > 0) _streamH3Raw.erase(_streamH3Raw.begin(), _streamH3Raw.begin() + static_cast<ptrdiff_t>(pos)); if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3Body.empty() if (q->isStreamComplete(_streamH3Sid) && _streamH3Raw.empty() && _streamH3BodyPos >= _streamH3Body.size() && !_streamH3InDataFrame && !q->hasStreamData(_streamH3Sid)) _streamH3EndStream = true; if (!_streamH3Body.empty()) { size_t have = _streamH3Body.size(); if (_streamH3BodyPos < _streamH3Body.size()) { size_t have = _streamH3Body.size() - _streamH3BodyPos; size_t take = (std::min)(have, bufsize); std::memcpy(buf, _streamH3Body.data(), take); _streamH3Body.erase(_streamH3Body.begin(), _streamH3Body.begin() + (ptrdiff_t)take); std::memcpy(buf, _streamH3Body.data() + _streamH3BodyPos, take); _streamH3BodyPos += take; if (_streamH3BodyPos == _streamH3Body.size()) { _streamH3Body.clear(); _streamH3BodyPos = 0; } return take; } Loading Loading @@ -4322,6 +4342,12 @@ void libhttppp::HttpRequest::setRequestURL(const std::string &url){ void libhttppp::HttpForm::parse(libhttppp::HttpRequest &request){ // Clear previous results so re-parsing doesn't duplicate entries _multipartEntries.clear(); _urlEntries.clear(); _boundary.clear(); _contentType.clear(); if(request.getRequestType()==POSTREQUEST || request.getRequestType()==PUTREQUEST){ HttpHeader::HeaderData *ctype=request.getHeaderData("content-type"); Loading
src/http.h +1 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ namespace libhttppp { bool _streamH3EndStream = false; std::vector<uint8_t> _streamH3Raw; // raw frame buffer std::vector<char> _streamH3Body; // decoded DATA frames not yet consumed size_t _streamH3BodyPos = 0; // consumed offset into _streamH3Body bool _streamH3InDataFrame = false; // true when inside a partial DATA frame uint64_t _streamH3DataRemaining = 0; // bytes left in current DATA frame Loading