26#include <lwip/sockets.h>
40 : tcp(tcp), status_code(200), headerSent(false)
98 if (!jwtToken.empty())
100 headers[
"Authorization"] =
"Bearer " + jwtToken;
110 auto it =
headers.find(
"Content-Type");
111 return (it !=
headers.end()) ? it->second :
"text/html";
142 return "Unauthorized";
146 return "Internal Server Error";
161 std::ostringstream cookie;
162 cookie << name <<
"=" << value;
163 if (!options.empty())
165 cookie <<
"; " << options;
167 cookies.push_back(cookie.str());
176 std::ostringstream cookie;
177 cookie << name <<
"=; Max-Age=0";
178 if (!options.empty())
180 cookie <<
"; " << options;
182 cookies.push_back(cookie.str());
195 TRACE(
"HttpResponse::send()\n");
200 headers[
"Content-Length"] = std::to_string(
body.size());
204 headers[
"Content-Type"] =
"text/html";
207 std::ostringstream resp;
211 resp << h.first <<
": " << h.second <<
"\r\n";
213 for (
const auto &cookie :
cookies)
215 resp <<
"Set-Cookie: " << cookie <<
"\r\n";
219 std::string header_str = resp.str();
220 tcp->
send(header_str.c_str(), header_str.size());
225 TRACE(
"HttpResponse::send() completed\n");
235 std::ostringstream resp;
240 resp << h.first <<
": " << h.second <<
"\r\n";
242 for (
const auto &cookie :
cookies)
244 resp <<
"Set-Cookie: " << cookie <<
"\r\n";
248 resp <<
"Connection: close\r\n";
252 std::string header_str = resp.str();
253 tcp->
send(header_str.c_str(), header_str.size());
261void HttpResponse::start(
int code,
size_t contentLength,
const std::string &contentType,
const std::string &contentEncoding)
264 headers[
"Content-Length"] = std::to_string(contentLength);
265 headers[
"Content-Type"] = contentType;
266 if (!contentEncoding.empty())
268 headers[
"Content-Encoding"] = contentEncoding;
271 std::ostringstream resp;
275 resp << h.first <<
": " << h.second <<
"\r\n";
277 for (
const auto &cookie :
cookies)
279 resp <<
"Set-Cookie: " << cookie <<
"\r\n";
283 std::string header_str = resp.str();
284 tcp->
send(header_str.c_str(), header_str.size());
295 printf(
"Error: writeChunk called before start()\n");
299 int err =
tcp->
send(data, length);
302 printf(
"Error sending chunk: %zu\n", err);
303 printf(
"Error: %s\n", strerror(errno));
325 .
set(
"Content-Type",
"application/json")
326 .
send(
"{\"error\": \"Unauthorized\"}");
336 .
send(R
"({"error": "Not Found"})");
346 .
send(
"{\"error\": \"" + message +
"\"}");
354 this->
set(
"Content-Type",
"application/json")
361 return json(jsonObj.dump());
366 return json(jsonObj.dump(2));
374 this->
set(
"Content-Type",
"text/plain")
382 .
set(
"Location", url)
392 std::string result = tpl;
393 for (
const auto &[key, value] : context)
395 std::string placeholder =
"{{" + key +
"}}";
397 while ((pos = result.find(placeholder, pos)) != std::string::npos)
399 result.replace(pos, placeholder.length(), value);
400 pos += value.length();
420 const std::map<std::string, std::string>& context) {
443 return fileHandler.
serveFile(*
this, path.c_str());
454 if (!storage ||
body.empty())
458 reinterpret_cast<const unsigned char*
>(
body.data()),
Macro-based debug trace system with optional SD file logging.
#define TRACE_INIT(MODULE_NAME)
Declare trace usage in a source file for a given module.
#define TRACE(...)
Default trace (INFO level).
Abstract base class for all views in the PicoFramework.
HTTP file server and file handling helpers for static content.
HTTP HttpResponse class for managing status, headers, body, and streaming support.
Utility functions to send standard JSON responses using nlohmann::json.
Helper class for accessing the file system and serving file content.
bool serveFile(HttpResponse &res, const char *uri)
Serve a file to the client via the HttpResponse object.
virtual std::string render(const std::map< std::string, std::string > &context={}) const =0
Render the view body.
virtual std::string getContentType() const =0
Return the MIME content type for this view.
virtual void applyHeaders(HttpResponse &response) const
Optional hook to set response headers (e.g., Content-Disposition).
Represents an HTTP response object.
void sendUnauthorized()
Send a 401 Unauthorized JSON response.
int status_code
HTTP status code.
HttpResponse & setStatus(int code)
Alias for status().
std::string renderTemplate(const std::string &tpl, const std::map< std::string, std::string > &context)
Apply basic variable substitution in a template.
HttpResponse & toFile(const std::string &path, StorageManager *storage)
HttpResponse & setContentType(const std::string &content_type)
Set the Content-Type header.
void writeChunk(const char *data, size_t length)
Send a chunk of the response body.
HttpResponse & text(const std::string &textString)
Send a plain text string with correct content type.
int getSocket() const
Return the raw socket descriptor.
HttpResponse & set(const std::string &field, const std::string &value)
Set a generic header field.
void finish()
Finish the response (placeholder for potential finalization).
bool isHeaderSent() const
Check if the headers have already been sent.
HttpResponse & setAuthorization(const std::string &jwtToken)
Set an Authorization header with a JWT token.
void sendNotFound()
Send a 404 Not Found JSON response.
void endServerError(const std::string &msg)
Send a 500 Internal Server Error response.
HttpResponse & jsonFormatted(const nlohmann::json &jsonObj)
void sendHeaders()
Send only the headers (for chunked/streaming responses).
HttpResponse & json(const std::string &jsonString)
Send a JSON string/object with correct content type.
void send(const std::string &body)
Send a full response including headers and body.
HttpResponse & setCookie(const std::string &name, const std::string &value, const std::string &options)
Set a cookie to be sent with the response.
HttpResponse & clearCookie(const std::string &name, const std::string &options)
Clear a cookie by setting Max-Age=0.
HttpResponse & status(int code)
Set the HTTP status code.
Tcp * tcp
Pointer to the Tcp object for socket operations.
std::string getContentType() const
Get the current Content-Type header value.
std::string body
Full response body (client-side or buffered server content)
HttpResponse & setBody(const std::string &body)
Set the body of the response (string).
bool sendFile(const std::string &path)
Sends the specified file from mounted storage to the client.
std::vector< std::string > cookies
Set-Cookie headers (server only)
HttpResponse & redirect(const std::string &url, int statusCode)
Redirect the client to another URL.
std::map< std::string, std::string > headers
Response headers (server+client)
bool headerSent
Tracks whether headers have already been sent.
void reset()
Clear the response status, headers, and body.
void start(int code, size_t contentLength, const std::string &contentType="application/octet-stream", const std::string &contentEncoding="")
Begin a streaming response by sending headers.
std::string getStatusMessage(int code)
Convert an HTTP status code to its standard message.
HttpResponse & sendError(int statusCode, const std::string &code, const std::string &message)
HttpResponse & setHeader(const std::string &key, const std::string &value)
Alias for set() for custom headers.
Abstract base class for storage access and file operations.
virtual bool writeFile(const std::string &path, const std::vector< uint8_t > &data)=0
Write a memory buffer to a file.
General-purpose TCP socket wrapper with optional TLS support via mbedTLS (altcp).
int send(const char *buffer, size_t size)
Send data over the connection.
int getSocketFd() const
Get the raw socket file descriptor (may be -1 for TLS-only connection).
Delegates to user or system configuration.
void sendError(HttpResponse &res, int statusCode, const std::string &code, const std::string &message)
System utilities for diagnostics, memory, stack usage, and tracing.