/* 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