libhttppp ..

Loading...
Searching...
No Matches
http.h
1/*******************************************************************************
2 Copyright (c) 2014, Jan Koester jan.koester@gmx.net
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the <organization> nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*******************************************************************************/
27
28#include <stddef.h>
29#include <sys/types.h>
30
31#include <vector>
32#include <string>
33#include <memory>
34#include <deque>
35#include <map>
36
37#include <netplus/socket.h>
38#include <netplus/connection.h>
39#include <netplus/eventapi.h>
40
41#include "config.h"
42
43#include "httpdefinitions.h"
44#include "hpack.h"
45
46#pragma once
47
48 namespace libhttppp::qpack { struct HeaderField; }
49
50 namespace libhttppp {
51 class HttpRequest;
52
53 class HttpUrl {
54 public:
55 enum HttpProtocol{
56 HTTP=0,
57 HTTPS=1,
58 HTTP3=2
59 };
60
61 HttpUrl();
62 HttpUrl(const std::string &url,bool http3=false);
63 HttpUrl(const HttpUrl &src);
64 ~HttpUrl();
65
66 bool operator==(const HttpUrl& other) const;
67 bool operator<(const HttpUrl& other) const;
68
69 int getProtocol() const;
70 const std::string &getHost() const;
71 int getPort() const;
72 const std::string &getPath() const;
73
74 void clear();
75
76 std::string print() const;
77
78 private:
79 int _protocol;
80 std::string _host;
81 int _port;
82 std::string _path;
83 };
84
85 class HttpClient{
86 public:
87 HttpClient( const HttpUrl &desturl);
88 ~HttpClient()=default;
89 void reconnect();
90 const std::vector<char> Get(HttpRequest &nreq);
91 const std::vector<char> Post(HttpRequest &nreq,const std::vector<char> &post);
92 private:
93 void resetConnection();
94 int readchunk(const char *data,int datasize,int &pos);
95
96 // HTTP/2 client helpers
97 bool _isH2 = false;
98 const std::vector<char> _h2Request(const std::string &method,
99 HttpRequest &nreq,
100 const std::vector<char> *postBody = nullptr);
101 private:
102 HttpUrl _url;
103 std::unique_ptr<netplus::socket> _cltsock;
104 netplus::x509cert _cert;
105 };
106
107
108 class HttpHeader {
109 public:
110 class HeaderData{
111 public:
112 class Values{
113 public:
114 Values &operator=(const std::string &val);
115 Values &operator=(size_t val);
116 Values &operator=(int val);
117 Values& operator=(const Values &val);
118
119 Values &operator<<(const std::string &value);
120 Values &operator<<(size_t value);
121 Values &operator<<(int value);
122
123 const std::string &getvalue();
124 int getIntvalue();
125 size_t getSizetValue();
126
127 Values *nextvalue();
128 Values(const std::string& val);
129 Values(const Values& val);
130 Values()=default;
131 ~Values() = default;
132 private:
133 std::string _value;
134 std::unique_ptr<Values> _nextvalue=nullptr;
135 friend class HeaderData;
136 };
137
138 Values *getfirstValue();
139 Values &at(int pos);
140 Values &operator[](int pos);
141
142 void push_back(const Values &val);
143 void push_back(const std::string &val);
144 void push_back(const char* val);
145 void push_back(size_t val);
146 void push_back(int val);
147
148 bool empty();
149
150 void erase(int pos);
151
152 void clear();
153
154 const std ::string &getkey();
155
156 HeaderData *nextHeaderData();
157 HeaderData(const std ::string &key);
158 ~HeaderData() = default;
159 private:
160 std::string _Key;
161 std::unique_ptr<Values> _firstValue=nullptr;
162 Values *_lastValue=nullptr;
163 std::unique_ptr<HeaderData> _nextHeaderData=nullptr;
164 friend class HttpHeader;
165 };
166
167 HeaderData *getfirstHeaderData();
168 HeaderData *getHeaderData(const std ::string &key) const;
169 HeaderData *setHeaderData(const std ::string &key);
170
171 void deldata(const std ::string &key);
172 void deldata(HeaderData*pos);
173
174 size_t getElements();
175 size_t getHeaderSize();
176
177 void clear();
178 protected:
179 HttpHeader();
180 virtual ~HttpHeader()=default;
181 std::unique_ptr<HeaderData> _firstHeaderData;
182 HeaderData *_lastHeaderData;
183 };
184
185 class HttpResponse : public HttpHeader,public netplus::con {
186 public:
187 HttpResponse();
188 HttpResponse(const HttpResponse &src);
189 ~HttpResponse();
190
191 /*server methods*/
192 void setState(const std ::string &httpstate);
193 void setContentType(const std ::string &type);
194 void setContentLength(size_t len);
195 void setConnection(const std ::string &type);
196 void setTransferEncoding(const std ::string &enc);
197
198 /*client methods*/
199 const std ::string &getState() const;
200 int getStatusCode() const;
201 const std ::string &getContentType() const;
202 size_t getContentLength() const;
203 const std ::string &getConnection() const;
204 const std ::string &getVersion() const;
205 HttpHeader::HeaderData::Values *getTransferEncoding() const;
206
207 size_t printHeader(std::vector<char> &buffer);
208
209 /*server methods*/
210 void send(netplus::con &curconnection,const std::string &data,int datalen=0); //only use as server
211 void send(netplus::con &curconnection,const unsigned char *data,int datalen); //only use as server
212 void send(netplus::con &curconnection,const std::vector<char> &data,int datalen=0); //only use as server
213
214 /*client method*/
215 size_t parse(const char *in,size_t inlen);
216
217 private:
218 bool _storeResponseInfo(netplus::con &curconnection, int datalen);
219
220 std::string _State=HTTP200;
221 std::string _Version;
222 int _StatusCode=200;
223 HeaderData *_TransferEncoding;
224 HeaderData *_Connection;
225 HeaderData *_ContentType;
226 HeaderData *_ContentLength;
227 mutable std::string _ContentTypeCache;
228 };
229
230
231 class HttpRequest : public HttpHeader, public netplus::con{
232 public:
233 HttpRequest();
234 HttpRequest(netplus::eventapi *evapi);
235 ~HttpRequest();
236
237 void clear();
238
239 /*server methods*/
240
241 size_t parse(); //only use as server
242
243 /*protocol-specific parse helpers (all store into _firstHeaderData)*/
244 size_t parseH2(const std::vector<hpack::HeaderField> &headers, uint32_t stream_id = 0);
245 size_t parseH3(const std::vector<qpack::HeaderField> &headers);
246
247 void printHeader(std::string &buffer);
248 int getRequestType();
249 const std::string &getRequestURL();
250 const std::string &getRequest();
251 size_t getRequestLength();
252 const std::string &getRequestVersion();
253 size_t getContentLength();
254 size_t getMaxUploadSize();
255
256 /*mobilphone switch*/
257 bool isMobile();
258
259 /*Client methods*/
260 void setRequestType(int req);
261 void setRequestURL(const std::string &url);
262 void setRequestVersion(const std::string &version);
263 /*only for post Reuquesttype*/
264 void setRequestData(const std::string &data,size_t len);
265 void setMaxUploadSize(size_t upsize);
266
267 void send(const HttpUrl &dest,std::unique_ptr<netplus::socket> &sock);
268
269 private:
270 size_t parseH1(); // HTTP/1.x request parsing
271
272 /*
273 * Helper: extracts URL path from :path header (strips query string).
274 * Used by getRequestURL() and parse helpers.
275 */
276 static std::string extractPath(const std::string &target);
277
278 int _RequestType = PARSEREQUEST;
279 size_t _MaxUploadSize = DEFAULT_UPLOADSIZE;
280
281 // Cached strings derived from _firstHeaderData pseudo-headers.
282 // Populated by parseH1/parseH2/parseH3, read by getters.
283 mutable std::string _cachedRequestURL;
284 mutable std::string _cachedRequest;
285 mutable std::string _cachedRequestVersion;
286
287 // HTTP/2 and HTTP/3 protocol state (managed by HttpEvent).
288 // All H2-specific mutable state lives in a heap-allocated struct so
289 // that inline-layout corruption of HttpRequest cannot trash the
290 // deque / map / decoder internals.
291 int _httpProtocol = 0; // 0=HTTP/1.x, 1=HTTP/2, 2=HTTP/3
292
293 struct H2PendingResponse {
294 uint32_t streamId;
295 std::string body; // remaining body data to send as DATA frames
296 size_t offset = 0; // how far into body we've sent
297 };
298
299 struct H2PendingIncoming {
300 std::vector<hpack::HeaderField> headers;
301 std::string body;
302 };
303
304 struct H2State {
305 uint32_t streamId = 0;
306 bool headersSent = false;
307 size_t expectedContentLength = 0;
308 size_t bodyBytesSent = 0;
309 std::deque<H2PendingResponse> pendingResponses;
310 std::map<uint32_t, H2PendingIncoming> pendingIncoming;
311 hpack::Decoder hpackDecoder;
312 };
313
314 // Lazily allocated when the connection is upgraded to HTTP/2.
315 std::unique_ptr<H2State> _h2;
316
317 // Allocate H2 state if not yet present; return reference.
318 H2State &h2state() {
319 if (!_h2) _h2 = std::make_unique<H2State>();
320 return *_h2;
321 }
322
323 friend class HttpForm;
324 friend class HttpResponse;
325 friend class HttpEvent;
326 };
327
328 class HttpForm {
329 public:
330 // ─── Multipart form-data (RFC 2046) ───────────────────
331 struct MultipartEntry {
332 struct Header {
333 std::string key; // lowercased header name (e.g. "content-disposition")
334 std::string value; // full header value
335 };
336
337 struct Disposition {
338 std::string key; // e.g. "name", "filename"
339 std::string value; // e.g. "field1", "upload.txt"
340 };
341
342 std::vector<Header> headers;
343 std::vector<Disposition> dispositions;
344 std::vector<char> value; // raw body (binary-safe for file uploads)
345 };
346
347 // ─── URL-encoded form data ────────────────────────────
348 struct UrlEntry {
349 std::string key;
350 std::string value;
351 };
352
353 HttpForm() = default;
354 ~HttpForm() = default;
355
356 void parse(HttpRequest &request);
357
358 // Accessors
359 const std::string &getContentType() const { return _contentType; }
360 const std::string &getBoundary() const { return _boundary; }
361 const std::vector<MultipartEntry> &multipartData() const { return _multipartEntries; }
362 const std::vector<UrlEntry> &urlData() const { return _urlEntries; }
363
364 // URL encoding / decoding utilities
365 static void urlDecode(const std::string &in, std::string &out);
366 static void urlEncode(const std::string &in, std::string &out);
367
368 private:
369 void _parseMultipart(const char *data, size_t len);
370 void _parseMultiSection(const char *data, size_t len, size_t start, size_t end);
371 void _parseUrlDecode(const char *data, size_t len);
372
373 std::string _boundary;
374 std::string _contentType;
375 std::vector<MultipartEntry> _multipartEntries;
376 std::vector<UrlEntry> _urlEntries;
377 };
378
379 class HttpCookie {
380 public:
381 class CookieData {
382 public:
383 CookieData *nextCookieData() const;
384 const std::string &getKey() const;
385 const std::string &getValue() const;
386 CookieData()=default;
387 CookieData(const CookieData& src);
388 ~CookieData();
389 private:
390 std::string _Key;
391 std::string _Value;
392 std::unique_ptr <CookieData> _nextCookieData=nullptr;
393
394 friend class HttpCookie;
395 };
396 HttpCookie();
397 ~HttpCookie();
398 void parse(libhttppp::HttpRequest& curreq);
399 void setcookie(libhttppp::HttpResponse& curresp,
400 const std::string &key,const std::string &value,
401 const std::string &comment="",const std::string &domain="",
402 int maxage=-1,const std::string &path="",
403 bool secure=false,const std::string &version="1",const std::string &samesite="",bool httponly=false);
404 CookieData *getfirstCookieData();
405 CookieData *getlastCookieData();
406 CookieData *addCookieData();
407 private:
408 std::unique_ptr <CookieData> _firstCookieData;
409 CookieData *_lastCookieData;
410 };
411
412#define BASICAUTH 0
413#define DIGESTAUTH 1
414#define NTLMAUTH 2
415
416 class HttpAuth {
417 public:
418 HttpAuth();
419 ~HttpAuth();
420 void parse(libhttppp::HttpRequest &curreq);
421 void setAuth(libhttppp::HttpResponse &curresp);
422
423 void setAuthType(int authtype);
424 void setRealm(const std::string &realm);
425 void setUsername(const std::string &username);
426 void setPassword(const std::string &password);
427
428 const std::string &getUsername();
429 const std::string &getPassword();
430 int getAuthType();
431 const std::string &getAuthRequest();
432
433 private:
434 int _Authtype;
435 std::string _Username;
436 std::string _Password;
437 std::string _Realm;
438 std::string _Nonce;
439
440 };
441};
libhttppp::HTTPS
Definition https.h:38
libhttppp::HttpAuth
Definition http.h:416
libhttppp::HttpClient
Definition http.h:85
libhttppp::HttpCookie::CookieData
Definition http.h:381
libhttppp::HttpCookie
Definition http.h:379
libhttppp::HttpEvent
Definition httpd.h:47
libhttppp::HttpForm
Definition http.h:328
libhttppp::HttpHeader::HeaderData::Values
Definition http.h:112
libhttppp::HttpHeader::HeaderData
Definition http.h:110
libhttppp::HttpHeader
Definition http.h:108
libhttppp::HttpRequest
Definition http.h:231
libhttppp::HttpResponse
Definition http.h:185
libhttppp::HttpUrl
Definition http.h:53
libhttppp::hpack::Decoder
Definition hpack.h:68
libhttppp::HttpForm::MultipartEntry::Disposition
Definition http.h:337
libhttppp::HttpForm::MultipartEntry::Header
Definition http.h:332
libhttppp::HttpForm::MultipartEntry
Definition http.h:331
libhttppp::HttpForm::UrlEntry
Definition http.h:348