106 void setTimeout(
int timeout_sec);
107 const std::vector<char> Get(
HttpRequest &nreq,
size_t maxTries=0);
108 const std::vector<char> Post(
HttpRequest &nreq,
const std::vector<char> &post,
size_t maxTries=0);
109 const std::vector<char> Put(
HttpRequest &nreq,
const std::vector<char> &put,
size_t maxTries=0);
110 const std::vector<char> Delete(
HttpRequest &nreq,
size_t maxTries=0);
126 size_t readBodyChunk(
char *buf,
size_t bufsize);
130 size_t readBodyChunkNonBlocking(
char *buf,
size_t bufsize);
133 bool isStreaming()
const;
138 bool waitReadable(
int timeout_ms);
142 void setMaxRedirects(
int max) { _maxRedirects = max; }
145 int lastStatusCode()
const {
return _lastStatusCode; }
148 const std::string &lastContentType()
const {
return _lastContentType; }
151 const HttpResponse *lastResponse()
const {
return _lastResponse.get(); }
154 void resetConnection();
158 static netplus::TlsSessionCache& tlsSessionCache();
160 void _ensureConnected();
163 void _connectTcp(netplus::tcp &sock);
164 bool tryHttp3First();
167 size_t _recvBlocking(netplus::buffer &b,
int timeout_sec = 0);
169 size_t _recvNonBlocking(netplus::buffer &b);
170 void _sendAll(
const char *data,
size_t len);
171 void _sendAll(
const std::string &data);
174 std::vector<char> _h1ReadResponse(
const std::string &label);
184 bool _streamRecvMore(
bool blocking,
bool &eof);
185 size_t _streamReadChunked(
char *buf,
size_t bufsize,
bool blocking);
186 size_t _streamReadEof(
char *buf,
size_t bufsize,
bool blocking);
195 size_t _streamReadH2(
char *buf,
size_t bufsize,
bool blocking);
202 size_t _streamReadH3(
char *buf,
size_t bufsize,
bool blocking);
209 const std::vector<char> _doH1Request(
const std::string &method,
int requestType,
211 size_t maxTries,
bool followRedirects);
216 bool _h2PrefaceSent =
false;
219 uint32_t _h2NextStreamId = 1;
220 std::unique_ptr<hpack::Decoder> _h2Decoder;
221 const std::vector<char> _h2Request(
const std::string &method,
223 const std::vector<char> *postBody =
nullptr);
224 const std::vector<char> _h3Request(
const std::string &method,
226 const std::vector<char> *postBody =
nullptr);
229 enum StreamMode { STREAM_NONE, STREAM_CONTENT_LENGTH, STREAM_CHUNKED, STREAM_EOF,
230 STREAM_H2, STREAM_H3 };
231 StreamMode _streamMode = STREAM_NONE;
232 size_t _streamRemaining = 0;
233 std::vector<char> _streamBuf;
234 size_t _streamBufPos = 0;
236 bool _streamChunkDone =
false;
237 size_t _streamChunkRemaining = 0;
240 uint32_t _streamH2Sid = 0;
241 bool _streamH2EndStream =
false;
242 std::vector<uint8_t> _streamH2Raw;
245 uint64_t _streamH3Sid = 0;
246 bool _streamH3EndStream =
false;
247 std::vector<uint8_t> _streamH3Raw;
248 std::vector<char> _streamH3Body;
249 size_t _streamH3BodyPos = 0;
250 bool _streamH3InDataFrame =
false;
251 uint64_t _streamH3DataRemaining = 0;
255 std::unique_ptr<netplus::socket> _cltsock;
256 netplus::socketwait _sw;
257 netplus::x509cert _cert;
267 netplus::buffer _recvScratch{CHUNKSIZE};
268 int _recvTimeoutSec = 60;
269 int _sendTimeoutSec = 30;
273 int _lastStatusCode = 0;
274 std::string _lastLocation;
275 std::string _lastContentType;
276 std::unique_ptr<HttpResponse> _lastResponse;
277 static constexpr int MAX_REDIRECTS = 5;
278 int _maxRedirects = MAX_REDIRECTS;
377 void setState(
const std ::string &httpstate);
378 void setContentType(
const std ::string &type);
379 void setContentLength(
size_t len);
380 void setConnection(
const std ::string &type);
381 void setTransferEncoding(
const std ::string &enc);
384 const std ::string &getState()
const;
385 int getStatusCode()
const;
386 const std ::string &getContentType()
const;
387 size_t getContentLength()
const;
388 const std ::string &getConnection()
const;
389 const std ::string &getVersion()
const;
392 size_t printHeader(std::vector<char> &buffer);
395 void send(netplus::con &curconnection,
const std::string &data,
int datalen=0);
396 void send(netplus::con &curconnection,
const unsigned char *data,
int datalen);
397 void send(netplus::con &curconnection,
const std::vector<char> &data,
int datalen=0);
404 void sendChunkedHeaders(netplus::con &curconnection);
405 void sendChunk(netplus::con &curconnection,
const char *data,
size_t len);
406 void endChunked(netplus::con &curconnection);
409 size_t parse(
const char *in,
size_t inlen);
418 size_t parseH2(
const std::vector<hpack::HeaderField> &headers);
419 size_t parseH3(
const std::vector<qpack::HeaderField> &headers);
422 bool _storeResponseInfo(netplus::con &curconnection,
int datalen);
424 std::string _State=HTTP200;
425 std::string _Version;
431 mutable std::string _ContentTypeCache;
448 size_t parseH2(
const std::vector<hpack::HeaderField> &headers, uint32_t stream_id = 0);
449 size_t parseH3(
const std::vector<qpack::HeaderField> &headers);
451 void printHeader(std::string &buffer);
452 int getRequestType();
453 const std::string &getRequestURL();
454 const std::string &getRequest();
455 size_t getRequestLength();
456 const std::string &getRequestVersion();
457 const std::string &getHost();
458 size_t getContentLength();
459 size_t getMaxUploadSize();
465 bool isChunkedRequest();
466 int decodeChunkedBody();
472 void setRequestType(
int req);
473 void setRequestURL(
const std::string &url);
474 void setRequestVersion(
const std::string &version);
476 void setRequestData(
const std::string &data,
size_t len);
477 void setMaxUploadSize(
size_t upsize);
479 void send(
const HttpUrl &dest,std::unique_ptr<netplus::socket> &sock);
488 static std::string extractPath(
const std::string &target);
490 int _RequestType = PARSEREQUEST;
491 size_t _MaxUploadSize = DEFAULT_UPLOADSIZE;
495 mutable std::string _cachedRequestURL;
496 mutable std::string _cachedRequest;
497 mutable std::string _cachedRequestVersion;
498 mutable std::string _cachedHost;
504 int _httpProtocol = 0;
506 struct H2PendingResponse {
514 struct H2StreamingResponse {
515 uint32_t streamId = 0;
516 size_t contentLength = 0;
517 size_t totalSent = 0;
518 std::string pendingData;
519 size_t pendingOffset = 0;
520 std::unique_ptr<HttpRequest> tempreq;
523 size_t emptyCount = 0;
524 unsigned int backoffMs = 1;
525 bool finished =
false;
532 bool windowBlocked =
false;
533 std::chrono::steady_clock::time_point blockedSince{};
536 struct H2PendingIncoming {
537 std::vector<hpack::HeaderField> headers;
539 std::vector<uint8_t> rawHpack;
540 bool headersComplete =
false;
541 bool endStreamOnHeaders =
false;
542 bool streaming =
false;
546 uint32_t streamId = 0;
547 bool headersSent =
false;
548 bool serverPrefaceSent =
false;
549 size_t expectedContentLength = 0;
550 size_t bodyBytesSent = 0;
551 std::deque<H2PendingResponse> pendingResponses;
552 std::map<uint32_t, H2PendingIncoming> pendingIncoming;
555 int32_t peerConnWindow = 65535;
556 int32_t peerInitialStreamWindow = 65535;
557 size_t peerMaxFrameSize = 16384;
558 std::map<uint32_t, int32_t> peerStreamWindows;
560 std::map<uint32_t, std::shared_ptr<H2StreamingResponse>> activeStreams;
564 std::unique_ptr<H2State> _h2;
568 if (!_h2) _h2 = std::make_unique<H2State>();
591 std::vector<Header> headers;
592 std::vector<Disposition> dispositions;
593 std::vector<char> value;
608 const std::string &getContentType()
const {
return _contentType; }
609 const std::string &getBoundary()
const {
return _boundary; }
610 const std::vector<MultipartEntry> &multipartData()
const {
return _multipartEntries; }
611 const std::vector<UrlEntry> &urlData()
const {
return _urlEntries; }
614 static void urlDecode(
const std::string &in, std::string &out);
615 static void urlEncode(
const std::string &in, std::string &out);
618 void _parseMultipart(
const char *data,
size_t len);
619 void _parseMultiSection(
const char *data,
size_t len,
size_t start,
size_t end);
620 void _parseUrlDecode(
const char *data,
size_t len);
622 std::string _boundary;
623 std::string _contentType;
624 std::vector<MultipartEntry> _multipartEntries;
625 std::vector<UrlEntry> _urlEntries;