105 void setTimeout(
int timeout_sec);
106 const std::vector<char> Get(
HttpRequest &nreq,
size_t maxTries=0);
107 const std::vector<char> Post(
HttpRequest &nreq,
const std::vector<char> &post,
size_t maxTries=0);
108 const std::vector<char> Put(
HttpRequest &nreq,
const std::vector<char> &put,
size_t maxTries=0);
109 const std::vector<char> Delete(
HttpRequest &nreq,
size_t maxTries=0);
125 size_t readBodyChunk(
char *buf,
size_t bufsize);
129 size_t readBodyChunkNonBlocking(
char *buf,
size_t bufsize);
132 bool isStreaming()
const;
137 bool waitReadable(
int timeout_ms);
141 void setMaxRedirects(
int max) { _maxRedirects = max; }
144 int lastStatusCode()
const {
return _lastStatusCode; }
147 const std::string &lastContentType()
const {
return _lastContentType; }
150 const HttpResponse *lastResponse()
const {
return _lastResponse.get(); }
153 void resetConnection();
157 static netplus::TlsSessionCache& tlsSessionCache();
159 void _ensureConnected();
162 void _connectTcp(netplus::tcp &sock);
163 bool tryHttp3First();
164 int readchunk(
const char *data,
int datasize,
int &pos);
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);
178 bool _h2PrefaceSent =
false;
181 uint32_t _h2NextStreamId = 1;
182 std::unique_ptr<hpack::Decoder> _h2Decoder;
183 const std::vector<char> _h2Request(
const std::string &method,
185 const std::vector<char> *postBody =
nullptr);
186 const std::vector<char> _h3Request(
const std::string &method,
188 const std::vector<char> *postBody =
nullptr);
191 enum StreamMode { STREAM_NONE, STREAM_CONTENT_LENGTH, STREAM_CHUNKED, STREAM_EOF,
192 STREAM_H2, STREAM_H3 };
193 StreamMode _streamMode = STREAM_NONE;
194 size_t _streamRemaining = 0;
195 std::vector<char> _streamBuf;
196 size_t _streamBufPos = 0;
198 bool _streamChunkDone =
false;
199 size_t _streamChunkRemaining = 0;
202 uint32_t _streamH2Sid = 0;
203 bool _streamH2EndStream =
false;
204 std::vector<uint8_t> _streamH2Raw;
207 uint64_t _streamH3Sid = 0;
208 bool _streamH3EndStream =
false;
209 std::vector<uint8_t> _streamH3Raw;
210 std::vector<char> _streamH3Body;
211 size_t _streamH3BodyPos = 0;
212 bool _streamH3InDataFrame =
false;
213 uint64_t _streamH3DataRemaining = 0;
217 std::unique_ptr<netplus::socket> _cltsock;
218 netplus::socketwait _sw;
219 netplus::x509cert _cert;
220 int _recvTimeoutSec = 60;
221 int _sendTimeoutSec = 30;
225 int _lastStatusCode = 0;
226 std::string _lastLocation;
227 std::string _lastContentType;
228 std::unique_ptr<HttpResponse> _lastResponse;
229 static constexpr int MAX_REDIRECTS = 5;
230 int _maxRedirects = MAX_REDIRECTS;
318 void setState(
const std ::string &httpstate);
319 void setContentType(
const std ::string &type);
320 void setContentLength(
size_t len);
321 void setConnection(
const std ::string &type);
322 void setTransferEncoding(
const std ::string &enc);
325 const std ::string &getState()
const;
326 int getStatusCode()
const;
327 const std ::string &getContentType()
const;
328 size_t getContentLength()
const;
329 const std ::string &getConnection()
const;
330 const std ::string &getVersion()
const;
333 size_t printHeader(std::vector<char> &buffer);
336 void send(netplus::con &curconnection,
const std::string &data,
int datalen=0);
337 void send(netplus::con &curconnection,
const unsigned char *data,
int datalen);
338 void send(netplus::con &curconnection,
const std::vector<char> &data,
int datalen=0);
345 void sendChunkedHeaders(netplus::con &curconnection);
346 void sendChunk(netplus::con &curconnection,
const char *data,
size_t len);
347 void endChunked(netplus::con &curconnection);
350 size_t parse(
const char *in,
size_t inlen);
353 bool _storeResponseInfo(netplus::con &curconnection,
int datalen);
355 std::string _State=HTTP200;
356 std::string _Version;
362 mutable std::string _ContentTypeCache;
379 size_t parseH2(
const std::vector<hpack::HeaderField> &headers, uint32_t stream_id = 0);
380 size_t parseH3(
const std::vector<qpack::HeaderField> &headers);
382 void printHeader(std::string &buffer);
383 int getRequestType();
384 const std::string &getRequestURL();
385 const std::string &getRequest();
386 size_t getRequestLength();
387 const std::string &getRequestVersion();
388 const std::string &getHost();
389 size_t getContentLength();
390 size_t getMaxUploadSize();
396 bool isChunkedRequest();
397 int decodeChunkedBody();
403 void setRequestType(
int req);
404 void setRequestURL(
const std::string &url);
405 void setRequestVersion(
const std::string &version);
407 void setRequestData(
const std::string &data,
size_t len);
408 void setMaxUploadSize(
size_t upsize);
410 void send(
const HttpUrl &dest,std::unique_ptr<netplus::socket> &sock);
419 static std::string extractPath(
const std::string &target);
421 int _RequestType = PARSEREQUEST;
422 size_t _MaxUploadSize = DEFAULT_UPLOADSIZE;
426 mutable std::string _cachedRequestURL;
427 mutable std::string _cachedRequest;
428 mutable std::string _cachedRequestVersion;
429 mutable std::string _cachedHost;
435 int _httpProtocol = 0;
437 struct H2PendingResponse {
445 struct H2StreamingResponse {
446 uint32_t streamId = 0;
447 size_t contentLength = 0;
448 size_t totalSent = 0;
449 std::string pendingData;
450 size_t pendingOffset = 0;
451 std::unique_ptr<HttpRequest> tempreq;
454 size_t emptyCount = 0;
455 unsigned int backoffMs = 1;
456 bool finished =
false;
463 bool windowBlocked =
false;
464 std::chrono::steady_clock::time_point blockedSince{};
467 struct H2PendingIncoming {
468 std::vector<hpack::HeaderField> headers;
470 std::vector<uint8_t> rawHpack;
471 bool headersComplete =
false;
472 bool endStreamOnHeaders =
false;
473 bool streaming =
false;
477 uint32_t streamId = 0;
478 bool headersSent =
false;
479 bool serverPrefaceSent =
false;
480 size_t expectedContentLength = 0;
481 size_t bodyBytesSent = 0;
482 std::deque<H2PendingResponse> pendingResponses;
483 std::map<uint32_t, H2PendingIncoming> pendingIncoming;
486 int32_t peerConnWindow = 65535;
487 int32_t peerInitialStreamWindow = 65535;
488 size_t peerMaxFrameSize = 16384;
489 std::map<uint32_t, int32_t> peerStreamWindows;
491 std::map<uint32_t, std::shared_ptr<H2StreamingResponse>> activeStreams;
495 std::unique_ptr<H2State> _h2;
499 if (!_h2) _h2 = std::make_unique<H2State>();
522 std::vector<Header> headers;
523 std::vector<Disposition> dispositions;
524 std::vector<char> value;
539 const std::string &getContentType()
const {
return _contentType; }
540 const std::string &getBoundary()
const {
return _boundary; }
541 const std::vector<MultipartEntry> &multipartData()
const {
return _multipartEntries; }
542 const std::vector<UrlEntry> &urlData()
const {
return _urlEntries; }
545 static void urlDecode(
const std::string &in, std::string &out);
546 static void urlEncode(
const std::string &in, std::string &out);
549 void _parseMultipart(
const char *data,
size_t len);
550 void _parseMultiSection(
const char *data,
size_t len,
size_t start,
size_t end);
551 void _parseUrlDecode(
const char *data,
size_t len);
553 std::string _boundary;
554 std::string _contentType;
555 std::vector<MultipartEntry> _multipartEntries;
556 std::vector<UrlEntry> _urlEntries;