126 const netplus::TlsTrustPolicy &trustPolicy = noVerifyTrustPolicy());
129 void setTimeout(
int timeout_sec);
130 const std::vector<char> Get(
HttpRequest &nreq,
size_t maxTries=0);
131 const std::vector<char> Post(
HttpRequest &nreq,
const std::vector<char> &post,
size_t maxTries=0);
132 const std::vector<char> Put(
HttpRequest &nreq,
const std::vector<char> &put,
size_t maxTries=0);
133 const std::vector<char> Delete(
HttpRequest &nreq,
size_t maxTries=0);
134 const std::vector<char> Options(
HttpRequest &nreq,
size_t maxTries=0);
135 const std::vector<char> Head(
HttpRequest &nreq,
size_t maxTries=0);
136 const std::vector<char> Patch(
HttpRequest &nreq,
const std::vector<char> &patch,
size_t maxTries=0);
139 const std::vector<char> Request(
int requestType,
HttpRequest &nreq,
140 const std::vector<char> *body =
nullptr,
size_t maxTries=0);
156 size_t readBodyChunk(
char *buf,
size_t bufsize);
160 size_t readBodyChunkNonBlocking(
char *buf,
size_t bufsize);
163 bool isStreaming()
const;
170 bool wantsClose()
const {
return _peerWantsClose; }
175 bool waitReadable(
int timeout_ms);
179 void setMaxRedirects(
int max) { _maxRedirects = max; }
182 int lastStatusCode()
const {
return _lastStatusCode; }
185 const std::string &lastContentType()
const {
return _lastContentType; }
188 const HttpResponse *lastResponse()
const {
return _lastResponse.get(); }
191 void resetConnection();
195 static netplus::TlsSessionCache& tlsSessionCache();
197 netplus::TlsTrustPolicy _trustPolicy;
199 void _ensureConnected();
202 void _connectTcp(netplus::tcp &sock);
203 bool tryHttp3First();
206 size_t _recvBlocking(netplus::buffer &b,
int timeout_sec = 0);
208 size_t _recvNonBlocking(netplus::buffer &b);
209 void _sendAll(
const char *data,
size_t len);
210 void _sendAll(
const std::string &data);
213 std::vector<char> _h1ReadResponse(
const std::string &label);
223 bool _streamRecvMore(
bool blocking,
bool &eof);
224 size_t _streamReadChunked(
char *buf,
size_t bufsize,
bool blocking);
225 size_t _streamReadEof(
char *buf,
size_t bufsize,
bool blocking);
234 size_t _streamReadH2(
char *buf,
size_t bufsize,
bool blocking);
241 size_t _streamReadH3(
char *buf,
size_t bufsize,
bool blocking);
245 size_t _readBodyChunkNonBlockingRaw(
char *buf,
size_t bufsize);
252 const std::vector<char> _doH1Request(
const std::string &method,
int requestType,
254 size_t maxTries,
bool followRedirects);
259 bool _h2PrefaceSent =
false;
262 uint32_t _h2NextStreamId = 1;
263 std::unique_ptr<hpack::Decoder> _h2Decoder;
264 const std::vector<char> _h2Request(
const std::string &method,
266 const std::vector<char> *postBody =
nullptr);
267 const std::vector<char> _h3Request(
const std::string &method,
269 const std::vector<char> *postBody =
nullptr);
272 enum StreamMode { STREAM_NONE, STREAM_CONTENT_LENGTH, STREAM_CHUNKED, STREAM_EOF,
273 STREAM_H2, STREAM_H3 };
274 StreamMode _streamMode = STREAM_NONE;
275 size_t _streamRemaining = 0;
276 std::vector<char> _streamBuf;
277 size_t _streamBufPos = 0;
279 bool _streamChunkDone =
false;
280 size_t _streamChunkRemaining = 0;
283 uint32_t _streamH2Sid = 0;
284 bool _streamH2EndStream =
false;
285 std::vector<uint8_t> _streamH2Raw;
288 uint64_t _streamH3Sid = 0;
289 bool _streamH3EndStream =
false;
290 std::vector<uint8_t> _streamH3Raw;
291 std::vector<char> _streamH3Body;
292 size_t _streamH3BodyPos = 0;
293 bool _streamH3InDataFrame =
false;
294 uint64_t _streamH3DataRemaining = 0;
300 std::chrono::steady_clock::time_point _streamIdleSince{};
304 std::unique_ptr<netplus::socket> _cltsock;
305 netplus::socketwait _sw;
306 netplus::x509cert _cert;
316 netplus::buffer _recvScratch{CHUNKSIZE};
317 int _recvTimeoutSec = 60;
318 int _sendTimeoutSec = 30;
324 bool _peerWantsClose =
false;
327 int _lastStatusCode = 0;
328 std::string _lastLocation;
329 std::string _lastContentType;
330 std::unique_ptr<HttpResponse> _lastResponse;
331 static constexpr int MAX_REDIRECTS = 5;
332 int _maxRedirects = MAX_REDIRECTS;
431 void setState(
const std ::string &httpstate);
432 void setContentType(
const std ::string &type);
433 void setContentLength(
size_t len);
434 void setConnection(
const std ::string &type);
435 void setTransferEncoding(
const std ::string &enc);
438 const std ::string &getState()
const;
439 int getStatusCode()
const;
440 const std ::string &getContentType()
const;
441 size_t getContentLength()
const;
442 const std ::string &getConnection()
const;
443 const std ::string &getVersion()
const;
446 size_t printHeader(std::vector<char> &buffer);
449 void send(netplus::con &curconnection,
const std::string &data,
int datalen=0);
450 void send(netplus::con &curconnection,
const unsigned char *data,
int datalen);
451 void send(netplus::con &curconnection,
const std::vector<char> &data,
int datalen=0);
458 void sendChunkedHeaders(netplus::con &curconnection);
459 void sendChunk(netplus::con &curconnection,
const char *data,
size_t len);
460 void endChunked(netplus::con &curconnection);
463 size_t parse(
const char *in,
size_t inlen);
472 size_t parseH2(
const std::vector<hpack::HeaderField> &headers);
473 size_t parseH3(
const std::vector<qpack::HeaderField> &headers);
476 bool _storeResponseInfo(netplus::con &curconnection,
int datalen);
478 std::string _State=HTTP200;
479 std::string _Version;
485 mutable std::string _ContentTypeCache;
502 size_t parseH2(
const std::vector<hpack::HeaderField> &headers, uint32_t stream_id = 0);
503 size_t parseH3(
const std::vector<qpack::HeaderField> &headers);
505 void printHeader(std::string &buffer);
506 int getRequestType();
509 std::string getRequestMethod();
510 const std::string &getRequestURL();
511 const std::string &getRequest();
512 size_t getRequestLength();
513 const std::string &getRequestVersion();
514 const std::string &getHost();
515 size_t getContentLength();
516 size_t getMaxUploadSize();
522 bool isChunkedRequest();
523 int decodeChunkedBody();
538 void setPeerAddress(
const std::string &addr);
539 const std::string &getPeerAddress()
const;
542 void setRequestType(
int req);
543 void setRequestURL(
const std::string &url);
544 void setRequestVersion(
const std::string &version);
546 void setRequestData(
const std::string &data,
size_t len);
547 void setMaxUploadSize(
size_t upsize);
549 void send(
const HttpUrl &dest,std::unique_ptr<netplus::socket> &sock);
558 static std::string extractPath(
const std::string &target);
560 int _RequestType = PARSEREQUEST;
561 size_t _MaxUploadSize = DEFAULT_UPLOADSIZE;
565 mutable std::string _cachedRequestURL;
566 mutable std::string _cachedRequest;
567 mutable std::string _cachedRequestVersion;
568 mutable std::string _cachedHost;
569 std::string _peerAddress;
575 int _httpProtocol = 0;
577 struct H2PendingResponse {
585 struct H2StreamingResponse {
586 uint32_t streamId = 0;
587 size_t contentLength = 0;
588 size_t totalSent = 0;
589 std::string pendingData;
590 size_t pendingOffset = 0;
591 std::unique_ptr<HttpRequest> tempreq;
594 size_t emptyCount = 0;
595 unsigned int backoffMs = 1;
596 bool finished =
false;
603 bool windowBlocked =
false;
604 std::chrono::steady_clock::time_point blockedSince{};
607 struct H2PendingIncoming {
608 std::vector<hpack::HeaderField> headers;
610 std::vector<uint8_t> rawHpack;
611 bool headersComplete =
false;
612 bool endStreamOnHeaders =
false;
613 bool streaming =
false;
617 uint32_t streamId = 0;
618 bool headersSent =
false;
619 bool serverPrefaceSent =
false;
620 size_t expectedContentLength = 0;
621 size_t bodyBytesSent = 0;
622 std::deque<H2PendingResponse> pendingResponses;
623 std::map<uint32_t, H2PendingIncoming> pendingIncoming;
626 int32_t peerConnWindow = 65535;
627 int32_t peerInitialStreamWindow = 65535;
628 size_t peerMaxFrameSize = 16384;
629 std::map<uint32_t, int32_t> peerStreamWindows;
631 std::map<uint32_t, std::shared_ptr<H2StreamingResponse>> activeStreams;
635 std::unique_ptr<H2State> _h2;
639 if (!_h2) _h2 = std::make_unique<H2State>();
662 std::vector<Header> headers;
663 std::vector<Disposition> dispositions;
664 std::vector<char> value;
679 const std::string &getContentType()
const {
return _contentType; }
680 const std::string &getBoundary()
const {
return _boundary; }
681 const std::vector<MultipartEntry> &multipartData()
const {
return _multipartEntries; }
682 const std::vector<UrlEntry> &urlData()
const {
return _urlEntries; }
685 static void urlDecode(
const std::string &in, std::string &out);
686 static void urlEncode(
const std::string &in, std::string &out);
689 void _parseMultipart(
const char *data,
size_t len);
690 void _parseMultiSection(
const char *data,
size_t len,
size_t start,
size_t end);
691 void _parseUrlDecode(
const char *data,
size_t len);
693 std::string _boundary;
694 std::string _contentType;
695 std::vector<MultipartEntry> _multipartEntries;
696 std::vector<UrlEntry> _urlEntries;