/*
TessesFramework a library to make C++ easier for me, used in CrossLang:
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#pragma once
#include "../Streams/NetworkStream.hpp"
#include "../Date/Date.hpp"
#include "../Threading/Thread.hpp"
#include "HttpUtils.hpp"
#include "WebSocket.hpp"
#include
#include
namespace Tesses::Framework::Http {
class ServerContextData {
public:
virtual ~ServerContextData();
};
class ServerContext;
class ServerSentEvents {
std::vector> strms;
Tesses::Framework::Threading::Mutex mtx;
private:
void SendEventRaw(const std::string &evt);
public:
void SendRetry(uint32_t ms);
void SendRetry(std::chrono::milliseconds ms);
void SendRetry(Tesses::Framework::Date::TimeSpan ts);
void SendData(const std::string &message);
void SendData(const std::string &message, const std::string &dataType);
void SendId(const std::string &idVal);
void SendCustomEvent(const std::string &type, const std::string &value);
void SendComment(const std::string &comment);
friend class ServerContext;
};
class ServerContext {
bool sent;
bool debug;
std::vector> sse;
std::shared_ptr strm;
std::map data;
std::queue> headerhandlers;
public:
HttpDictionary requestHeaders;
HttpDictionary responseHeaders;
HttpDictionary queryParams;
// used by path
HttpDictionary pathArguments;
std::string path;
std::string originalPath;
std::string method;
StatusCode statusCode;
std::string ip;
uint16_t port;
uint16_t serverPort;
std::string version;
bool encrypted;
ServerContext(std::shared_ptr strm,
bool debug = false);
~ServerContext();
std::shared_ptr GetStream();
std::string GetOriginalPathWithQuery();
std::string GetUrlWithQuery();
bool Sent();
bool NeedToParseFormData();
void ParseFormData(
std::function(
std::string mime, std::string filename, std::string name)>
cb);
void ReadStream(std::shared_ptr strm);
std::string ReadString();
void SendBytes(std::vector buffer);
void SendText(std::string text);
void SendStream(std::shared_ptr strm);
void SendErrorPage(bool showPath);
void SendNotFound();
void SendBadRequest();
void SendException(std::exception &ex);
void SendServerSentEvents(std::shared_ptr sse);
std::shared_ptr OpenResponseStream();
std::shared_ptr OpenRequestStream();
ServerContext &WithStatusCode(StatusCode code);
ServerContext &WithLastModified(Date::DateTime time);
ServerContext &WithHeader(std::string key, std::string value);
ServerContext &WithSingleHeader(std::string key, std::string value);
ServerContext &WithMimeType(std::string mime);
ServerContext &WithContentDisposition(std::string filename, bool isInline);
ServerContext &WriteHeaders();
ServerContext &WithLocationHeader(std::string url);
ServerContext &WithLocationHeader(std::string url, StatusCode sc);
ServerContext &
WithHeaderIntercepter(std::function cb);
ServerContext &WithDebug(bool debug = true);
bool Debug();
void StartWebSocketSession(
std::function,
std::function, std::function)>
onOpen,
std::function onReceive,
std::function onClose);
void StartWebSocketSession(std::shared_ptr connection);
std::string GetServerRoot();
std::string MakeAbsolute(std::string path);
void SendRedirect(std::string url);
void SendRedirect(std::string url, StatusCode sc);
template T *GetServerContentData(std::string tag) {
std::string name = typeid(T).name();
name.push_back(' ');
name.append(tag);
if (data.count(name) > 0)
return dynamic_cast(data[name]);
T *item = new T();
data[name] = item;
return item;
}
friend class ServerSentEvents;
};
class IHttpServer {
public:
virtual bool Handle(ServerContext &ctx) = 0;
virtual ~IHttpServer();
};
class HttpServer {
std::shared_ptr server;
std::shared_ptr http;
Tesses::Framework::Threading::Thread *thrd;
bool showIPs;
bool showARTL;
bool debug;
public:
HttpServer(std::shared_ptr tcpServer,
std::shared_ptr http, bool showIPs = true,
bool debug = false);
HttpServer(uint16_t port, std::shared_ptr http,
bool showIPs = true, bool debug = false);
HttpServer(std::string unixPath, std::shared_ptr http,
bool debug = false);
uint16_t GetPort();
void StartAccepting();
static void
Process(std::shared_ptr strm,
std::shared_ptr server, std::string ip, uint16_t port,
uint16_t serverPort, bool encrypted, bool debug = false);
~HttpServer();
};
} // namespace Tesses::Framework::Http