Logo Pico-Framework A web-first embedded framework for C++
Loading...
Searching...
No Matches
HttpRequest.h
Go to the documentation of this file.
1
14#ifndef HTTPREQUEST_H
15#define HTTPREQUEST_H
16#pragma once
17
18#include <string>
19#include <map>
20#include <iostream>
21#include "network/Tcp.h"
22#include "utility/utility.h"
23#include "http/HttpResponse.h"
24
25class Router;
26
32{
33public:
34 // ─────────────────────────────────────────────────────────────────────────────
35 // Constructors
36 // ─────────────────────────────────────────────────────────────────────────────
37
44 HttpRequest(const char *rawHeaders, const std::string &reqMethod, const std::string &reqPath);
45
46 // used by fluent builder - client side
47 HttpRequest(const std::string &raw, const std::string &method, const std::string &path)
48 : method(method), uri(path), path(path) {}
49
50 // Server-side use — accepts Tcp* and parsed info
51 HttpRequest(Tcp *connection, const std::string rawHeaders, const std::string &method, const std::string &path)
52 : tcp(connection), method(method), uri(path), path(path)
53 {
54 parseHeaders(rawHeaders.c_str());
55 }
56
57 HttpRequest() = default;
58 HttpRequest(const HttpRequest &) = default;
59
60 // ─────────────────────────────────────────────────────────────────────────────
61 // Store a CA Root Certificate
62 // ─────────────────────────────────────────────────────────────────────────────
63
69 HttpRequest &setRootCACertificate(const std::string &certData);
70
71#if defined(PICO_HTTP_ENABLE_STORAGE)
78 bool setRootCACertificateFromFile(const char *path);
79#endif
80
81 // ─────────────────────────────────────────────────────────────────────────────
82 // Easy access methods for sending requests
83 // ─────────────────────────────────────────────────────────────────────────────
84
90
97 HttpResponse get(const std::string &url);
99 HttpResponse post(const std::string &url, const std::string &body);
101 HttpResponse put(const std::string &url, const std::string &body);
103 HttpResponse del(const std::string &url);
104
105 // ─────────────────────────────────────────────────────────────────────────────
106 // Header Accessors
107 // ─────────────────────────────────────────────────────────────────────────────
108
114 std::string getHeader(const std::string &field) const
115 {
116 auto it = headers.find(toLower(field));
117 return (it != headers.end()) ? it->second : "";
118 }
119
124 const std::map<std::string, std::string> &getHeaders() const
125 {
126 return headers;
127 }
128
132 void printHeaders() const
133 {
134 for (const auto &header : headers)
135 {
136 std::cout << header.first << ": " << header.second << std::endl;
137 }
138 }
139
144 void setHeaderEnd(size_t end)
145 {
146 headerEnd = end;
147 }
148
154 {
155 return headerEnd;
156 }
157
161 const std::string &getHost() const
162 {
163 return host;
164 }
165
166 const std::string &getProtocol() const
167 {
168 return protocol;
169 }
170
171 // ─────────────────────────────────────────────────────────────────────────────
172 // Content Type / Body Type Checkers
173 // ─────────────────────────────────────────────────────────────────────────────
174
178 bool isFormUrlEncoded() const
179 {
180 auto it = headers.find("content-type");
181 return it != headers.end() && it->second.find("application/x-www-form-urlencoded") != std::string::npos;
182 }
183
187 bool isJson() const
188 {
189 auto it = headers.find("content-type");
190 return it != headers.end() && it->second.find("application/json") != std::string::npos;
191 }
192
196 const std::string getContentType() const
197 {
198 return getHeader("content-type");
199 }
200
205 const std::string getBoundary() const
206 {
207 auto contentType = getContentType();
208 auto boundaryPos = contentType.find("boundary=");
209 if (boundaryPos != std::string::npos)
210 {
211 return contentType.substr(boundaryPos + 9);
212 }
213 return "";
214 }
215
219 bool isMultipart() const
220 {
221 auto contentType = getHeader("content-type");
222 return contentType.find("multipart/form-data") != std::string::npos;
223 }
224
225 // ─────────────────────────────────────────────────────────────────────────────
226 // Body Accessors
227 // ─────────────────────────────────────────────────────────────────────────────
228
232 const std::string &getBody() const
233 {
234 return body;
235 }
236
238 bool isBodyTruncated() const { return bodyTruncated; }
240
245 HttpRequest &setBody(const std::string &body); // Enables chaining
246
252 {
253 std::string content_length_str = getHeader("content-length");
254 int contentLength = 0;
255 if (!content_length_str.empty())
256 {
257 contentLength = std::stoi(content_length_str);
258 }
259 return contentLength;
260 }
261
269 inline nlohmann::json json() const
270 {
271 return nlohmann::json::parse(getBody(), nullptr, false);
272 }
273
274 // ─────────────────────────────────────────────────────────────────────────────
275 // Method / URL / Path Accessors
276 // ─────────────────────────────────────────────────────────────────────────────
277
281 HttpRequest &setMethod(const std::string &method)
282 {
283 this->method = method;
284 return *this;
285 }
286
290 HttpRequest &setPath(const std::string &path)
291 {
292 this->path = path;
293 return *this;
294 }
295
299 const std::string &getMethod() const
300 {
301 return method;
302 }
303
307 const std::string &getPath() const
308 {
309 return path;
310 }
311
315 const std::string &getUri() const
316 {
317 return uri;
318 }
319
323 const std::string &getQuery() const
324 {
325 return query;
326 }
327
328 // ─────────────────────────────────────────────────────────────────────────────
329 // Tcp accessors
330 // ─────────────────────────────────────────────────────────────────────────────
331
332 Tcp *getTcp() const
333 {
334 return tcp;
335 }
336
337 // ─────────────────────────────────────────────────────────────────────────────
338 // Cookie and Parameter Access
339 // ─────────────────────────────────────────────────────────────────────────────
340
345 const std::unordered_map<std::string, std::string> getCookies() const;
346
352 const std::string getCookie(const std::string &name) const;
353
357 const std::unordered_multimap<std::string, std::string> getQueryParams();
358
362 const std::unordered_multimap<std::string, std::string> getFormParams();
363
364 // ─────────────────────────────────────────────────────────────────────────────
365 // Socket-Based Helpers (Static)
366 // ─────────────────────────────────────────────────────────────────────────────
367
373 static HttpRequest receive(Tcp *tcp);
374
375
376
377 static std::optional<std::pair<std::string, std::string>> receiveUntilHeadersComplete(Tcp* conn);
378 bool appendRemainingBody(int expectedLength);
379
380
381
382
383
391 static bool getMethodAndPath(const std::string& data, std::string& method, std::string& path);
392
393 // ─────────────────────────────────────────────────────────────────────────────
394 // Multipart Upload Handling
395 // ─────────────────────────────────────────────────────────────────────────────
396
403 // ─────────────────────────────────────────────────────────────────────────────
404 // Fluent Builder Methods (Client Usage)
405 // ─────────────────────────────────────────────────────────────────────────────
406
407 static HttpRequest create(); // static builder factory
408 HttpRequest &setUri(const std::string &uri);
409 HttpRequest &setHost(const std::string &host);
410 HttpRequest &setProtocol(const std::string &protocol);
411 HttpRequest &setHeaders(const std::map<std::string, std::string> &headers);
412 HttpRequest &setHeader(const std::string &key, const std::string &value);
413 HttpRequest &setUserAgent(const std::string &userAgent);
414 HttpRequest &setAcceptEncoding(const std::string &encoding);
415
416 // ─────────────────────────────────────────────────────────────────────────────
417 // toFile: Save the request body to a file
418 // ─────────────────────────────────────────────────────────────────────────────
419
420 HttpRequest &toFile(const std::string &path);
421 std::string getOutputFilePath() const;
422 bool wantsToFile() const;
423
424 // ─────────────────────────────────────────────────────────────────────────────
425 // Root CA Certificate Access
426 // ─────────────────────────────────────────────────────────────────────────────
432 const std::string &getRootCACertificate() const
433 {
434 return rootCACertificate;
435 }
436
437#if defined(PICO_HTTP_ENABLE_STORAGE)
438 HttpRequest &setBodyFromFile(const std::string &path);
439#endif
440
441private:
442 void parseHeaders(const char *raw);
443 void appendToBody(const char *data, size_t len);
444
445 void setQueryString(const std::string &query)
446 {
447 this->query = query;
448 }
449
450 Tcp *tcp = nullptr;
451
452 std::string clientIp;
453 std::string method;
454 std::string uri;
455 std::string path;
456 std::string query;
457 std::string host;
458 std::string protocol;
459 std::map<std::string, std::string> headers; // optional
460 std::string body;
461 std::string rootCACertificate;
462 size_t headerEnd = 0;
463 bool bodyTruncated = false;
464 std::string outputFilePath;
465};
466
467#endif // HTTPREQUEST_H
HTTP HttpResponse class for managing status, headers, body, and streaming support.
General-purpose TCP socket abstraction with optional TLS support for both client and server use.
Forward declaration for potential routing needs.
Definition HttpRequest.h:32
HttpResponse get()
Send a GETPOST/PUT/DEL request.
const std::string & getBody() const
Get the request body (copy).
const std::map< std::string, std::string > & getHeaders() const
Get all request headers.
bool isFormUrlEncoded() const
Check if content-type is application/x-www-form-urlencoded.
HttpRequest & setUserAgent(const std::string &userAgent)
std::string getOutputFilePath() const
void setQueryString(const std::string &query)
std::string protocol
HttpRequest & setUri(const std::string &uri)
Set the URI for the request.
HttpRequest()=default
HttpResponse put()
void appendToBody(const char *data, size_t len)
HttpRequest(const std::string &raw, const std::string &method, const std::string &path)
Definition HttpRequest.h:47
std::string uri
const std::string & getMethod() const
Get the HTTP method.
static bool getMethodAndPath(const std::string &data, std::string &method, std::string &path)
Parse the HTTP method and path from the first request line.
std::string host
std::string clientIp
std::string outputFilePath
bool bodyTruncated
HttpRequest & setRootCACertificate(const std::string &certData)
Set the root CA certificate to use for TLS.
HttpRequest & setHost(const std::string &host)
HttpRequest & setMethod(const std::string &method)
Set the HTTP method (e.g., GET, POST).
bool wantsToFile() const
HttpRequest & setPath(const std::string &path)
Set the request path.
void printHeaders() const
Print all headers to the standard output.
const std::string & getRootCACertificate() const
Get the root CA certificate string, if set.
void parseHeaders(const char *raw)
std::string body
HttpRequest & toFile(const std::string &path)
std::string query
const std::string & getHost() const
Get the Host header value.
const std::unordered_multimap< std::string, std::string > getFormParams()
Get parsed form fields (application/x-www-form-urlencoded).
const std::unordered_multimap< std::string, std::string > getQueryParams()
Get parsed query string parameters.
static HttpRequest receive(Tcp *tcp)
Receive and parse an HTTP request from a socket.
std::string method
std::string path
int handle_multipart(HttpResponse &res)
Handle multipart/form-data uploads.
HttpRequest(const HttpRequest &)=default
const std::unordered_map< std::string, std::string > getCookies() const
Get all parsed cookies.
size_t getHeaderEnd()
Get the header end offset (used for body parsing).
static std::optional< std::pair< std::string, std::string > > receiveUntilHeadersComplete(Tcp *conn)
const std::string & getPath() const
Get the parsed request path (without query string).
const std::string getContentType() const
Get the raw Content-Type string.
HttpRequest & setProtocol(const std::string &protocol)
const std::string & getQuery() const
Get the parsed query string from the URL.
std::map< std::string, std::string > headers
nlohmann::json json() const
Safely parse the request body as JSON (non-throwing).
bool isJson() const
Check if content-type is application/json.
const std::string getCookie(const std::string &name) const
Get a specific cookie value.
int getContentLength() const
Get the Content-Length header as integer.
HttpResponse send()
Send the request and return the response.
size_t headerEnd
void setHeaderEnd(size_t end)
Set the position marking the end of headers.
HttpRequest & setHeaders(const std::map< std::string, std::string > &headers)
const std::string getBoundary() const
Get the boundary string (for multipart/form-data).
bool isMultipart() const
Check whether the request is multipart/form-data.
std::string rootCACertificate
HttpRequest & setAcceptEncoding(const std::string &encoding)
std::string getHeader(const std::string &field) const
Get a specific header field (case-insensitive).
HttpResponse del()
HttpRequest(Tcp *connection, const std::string rawHeaders, const std::string &method, const std::string &path)
Definition HttpRequest.h:51
static HttpRequest create()
void markBodyTruncated()
HttpRequest & setHeader(const std::string &key, const std::string &value)
HttpResponse post()
Tcp * getTcp() const
const std::string & getUri() const
Get the original URL from the request line.
bool appendRemainingBody(int expectedLength)
bool isBodyTruncated() const
Check if the request body was truncated due to memory limits.
const std::string & getProtocol() const
HttpRequest & setBody(const std::string &body)
Set the body of the request.
Represents an HTTP response object.
The central router for handling HTTP requests and middleware.
Definition Router.h:60
General-purpose TCP socket wrapper with optional TLS support via mbedTLS (altcp).
Definition Tcp.h:39
std::string toLower(std::string str)
Definition utility.cpp:93
System utilities for diagnostics, memory, stack usage, and tracing.