//
// File: hzHttpServer.h
//
// Legal Notice: This file is part of the HadronZoo C++ Class Library.
//
// Copyright 2025 HadronZoo Project (http://www.hadronzoo.com)
//
// The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free
// Software Foundation, either version 3 of the License, or any later version.
//
// The HadronZoo C++ Class Library 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses.
//
//
// This header describes the two further classes needed to interface to the hzIpServer instance in order to impliment an internet application.
// These are:-
//
// 1) hzHttpSession
// 2) hzHttpFile
// 3) hzHttpEvent
//
#ifndef hzHttpServer_h
#define hzHttpServer_h
#include "hzMimetype.h"
#include "hzChain.h"
#include "hzTmplArray.h"
#include "hzTmplMapS.h"
#include "hzIpServer.h"
#include "hzHttpProto.h"
#define HZ_MAX_HTTP_HDR 8192 // Note this is much smaller than that specified by Apache for example. There is no good reason for excessive proprietary
// lines in the HTTP header and use of data submissions are discouraged under Dissemino guidlines.
class hzHttpSession
{
// Category: Internet
//
// hzHttpSession is a pure virtual class whose purpose is to unify any application-level classes that allow the server to maintain state. The only menifestation in the library
// however, is the Dissemino class hdsInfo.
public:
virtual ~hzHttpSession () {}
} ;
class hzHttpFile
{
// Category: Internet
//
// Support class for hzHttpEvent to handle file uploads
public:
hzChain m_file ; // The file itself
hzString m_fldname ; // Name of field
hzString m_filename ; // Name of uploaded file
int32_t m_resv ; // Reserved
hzMimetype m_mime ; // MIME type of content
hzHttpFile (void)
{
m_resv = 0 ;
m_mime = HMTYPE_INVALID ;
}
hzHttpFile& operator= (const hzHttpFile& op)
{
m_file = op.m_file ;
m_fldname = op.m_fldname ;
m_filename = op.m_filename ;
m_resv = op.m_resv ;
m_mime = op.m_mime ;
return *this ;
}
// Serialization
operator const char* (void) const ;
} ;
class hzHttpEvent
{
// Category: Internet
//
// The hzHttpEvent class is the focal point of a HadronZoo/Dissemino Internet application. All HTTP requests (GET) or submissions (POST) generate
// and populates a hzHttpEvent instance which initially contains data supplied in the incoming request. Each time this occurs, the hzHttpEvent is
// passed to a user defined 'callback' function which processes it and generates a response. This process may add further data to the hzHttpEvent
// which is used to formulate the header for the outgoing HTTP response.
hzIpConnex* m_pCx ; // Connection to TCP server
hzLogger* m_pLog ; // Log channel (from connection)
hzHttpSession* m_pSession ; // HTTP session (set by app)
char* m_pBuf ; // Buffer for header values
char* m_pAccept ; // Accept mimetype eg text/plain
char* m_pAcceptCharset ; // Accept character set
char* m_pAcceptLang ; // Language e.g. US English
char* m_pAcceptCode ; // Encoding
char* m_pCacheControl ; // Cache Control
char* m_pConnection ; // Connection directive
char* m_pContentType ; // Content Type
char* m_pETag ; // Page ID checking
char* m_pPragma ; // Misc command
char* m_pUserAgent ; // Type of browser
char* m_pProcessor ; // Type of processor on browser computer
char* m_pVia ; // Some proxy servers send this
char* m_pCliIP ; // IP From Apache
char* m_pHost ; // The desired hostname
char* m_pXost ; // The desired hostname
char* m_pFwrdIP ; // IP From Apache
char* m_pProxIP ; // IP From Apache
char* m_pServer ; // The desired server
char* m_pFrom ; // Email address of person making request (not sure why this is but hey what the heck)
char* m_pReferer ; // Email address of person making request (not sure why this is but hey what the heck)
char* m_pReqPATH ; // Request path
char* m_pReqFRAG ; // Request path fragment
hzXDate m_LastMod ; // If last modified directive
//hzUrl m_Referer ; // Refered from URL.
hzString m_Referer ; // Refered from URL.
hzSysID m_CookieSub ; // Cookie submitted by the browser
hzSysID m_CookieNew ; // New cookie as set by server
hzSysID m_CookieOld ; // Redundant cookie from browser
hzString m_Redirect ; // Directive to browser URI
hzString m_Auth ; // Basic authorization
hzSDate m_CookieExpire ; // Expiry date (for setting permanent cookies only)
hzIpaddr m_ClientIP ; // This is either copied from the connection or if apache proxypass is in use, then it is set by an X-param
uint32_t m_nVersion ; // HTTP/1.0 or whatever.
uint32_t m_nHeaderLen ; // Actual length of header
uint32_t m_nContentLen ; // Actual length of the form data
uint32_t m_nQueryLen ; // Query length
uint32_t m_nMaxForwards ; // Max forwards
uint32_t m_nConnection ; // Positive value for keep-alive (no of seconds to live), 0 for close
uint32_t m_nCountry ; // Country code
HttpRC m_eRetCode ; // HTTP return code
HttpMethod m_eMethod ; // E.g. GET, HEAD or POST
bool m_bHdrComplete ; // False if hit's header incomplete
bool m_bMsgComplete ; // False if hit incomplete
bool m_bZipped ; // True if Accept-Encoding contains 'gzip'
uint32_t _setnvpairs (hzChain::Iter& cIter) ;
hzEcode _formhead (hzChain& Z, HttpRC hrc, hzMimetype type, uint32_t nSize, uint32_t nExpires, bool bZip) ;
// Prevent copies
hzHttpEvent (const hzHttpEvent&) ;
hzHttpEvent& operator= (const hzHttpEvent&) ;
public:
hzMapS <hzString,hzString> m_mapStrings ; // Populated by form submission (POST) events but also by SetVar() calls by the application
hzMapS <hzString,hzChain> m_mapChains ; // Populated by SetVar() function (used in Dissemino)
hzMapS <hzString,hzHttpFile> m_Uploads ; // List of uploaded files
hzMapS <hzString,uint32_t> m_ObjIds ; // Map of caches and objects ids (Dissemino only)
hzArray <hzPair> m_Inputs ; // Data submissions
hzList <hzPair> m_HdrsResponse ; // HTTP headers set in the response
//hzChain m_Track ; // Used by application to report on progress during the event. Logged when message processing is complete.
void* m_pContextApp ; // The applicable Dissemino application (set by the 'Host:' header in the HTTP request)
void* m_pContextLang ; // The applicable language (set by HTTP request processing)
void* m_pContextForm ; // Application specific context. Dissemino current form reference.
void* m_pContextObj ; // Application specific context. Dissemino current object.
hzXDate m_Occur ; // Exact time of hit
hzString m_Resarg ; // Resource argument (dissemino)
hzString m_LangCode ; // Page Language (in response)
hzString m_appError ; // This can be set by the application (eg form submission error)
// Variables to cope with Dissemino
hzChain m_Error ; // Set during form processing in order to pass error messages to the form response
hzChain m_Report ; // Set by function processing the hits
hzHttpEvent (hzChain& ZI, hzIpConnex* pCx) ;
hzHttpEvent (void) ;
~hzHttpEvent (void) ;
void Clear (void) ;
// Simple Set Functions
void SetLogger (hzLogger* pLog) { m_pLog = pLog ; }
void SetURI (const char* cpURI) { m_Redirect = cpURI ; }
void SetRetCode (HttpRC RetCode) { m_eRetCode = RetCode ; }
// Simple Get Functions
hzLogger* GetLogger (void) const { return m_pLog ; }
HttpRC GetRetCode (void) const { return m_eRetCode ; }
uint32_t EventNo (void) const { return m_pCx ? m_pCx->EventNo() : 0 ; }
uint32_t CliSocket (void) const { return m_pCx ? m_pCx->CliSocket() : 0 ; }
uint32_t HeaderLen (void) const { return m_nHeaderLen ; }
uint32_t ExpectSize (void) const { return m_nHeaderLen + m_nContentLen ; }
uint32_t QueryLen (void) const { return m_nQueryLen ; }
bool HdrComplete (void) const { return m_bHdrComplete ; }
bool MsgComplete (void) const { return m_bMsgComplete ; }
bool Zipped (void) const { return m_bZipped ; }
hzEcode GetAt (hzPair& P, uint32_t nIndex)
{
if (nIndex < 0 || nIndex >= m_Inputs.Count())
return E_RANGE ;
P = m_Inputs[nIndex] ;
return E_OK ;
}
uint32_t Inputs (void) const { return m_Inputs.Count() ; }
HttpMethod Method (void) const { return m_eMethod ; }
hzIpaddr ClientIP (void) const { return m_ClientIP ; }
//hzUrl Referer (void) const { return m_Referer ; }
hzString Referer (void) const { return m_Referer ; }
hzString Auth (void) const { return m_Auth ; }
hzSysID Cookie (void) const { return m_CookieSub ; }
const char* TxtClientIP (void) const { return m_pCliIP ; }
const char* TxtFwrdIP (void) const { return m_pFwrdIP ; }
const char* TxtProxIP (void) const { return m_pProxIP ; }
const char* ETag (void) const { return m_pETag ; }
const char* Hostname (void) const { return m_pHost ; }
const char* Server (void) const { return m_pServer ; }
const char* UserAgent (void) const { return m_pUserAgent ; }
const char* GetResource (void) const { return m_pReqPATH ; }
//const char* GetQuery (void) const { return m_pReqQURY ; }
const char* GetFragment (void) const { return m_pReqFRAG ; }
uint32_t Connection (void) const { return m_nConnection ; }
hzIpConnex* GetConnex (void) const { return m_pCx ; }
hzHttpSession* Session (void) const { return m_pSession ; }
// Set header (for response) to any type/any value
hzEcode SetHdr (const hzString& name, const hzString& value) ;
// Set variable to any type/any value
hzEcode SetVarString (const hzString& name, const hzString& value) ;
hzEcode SetVarChain (const hzString& name, const hzChain& value) ;
// Get variable functions
hzString GetVarStr (const hzString& name) { return m_mapStrings[name] ; }
hzChain GetVarChain (const hzString& name) { return m_mapChains[name] ; }
hzSDate CookieExpire (void) { return m_CookieExpire ; }
hzEcode GetVar (hzChain& Z, const hzString& name) ;
// Other operations
void SetSessCookie (const hzSysID& Cookie) ;
void SetPermCookie (const hzSysID& Cookie, hzSDate& expires) ;
void DelSessCookie (const hzSysID& Cookie) { m_CookieOld = Cookie ; }
void SetSession (hzHttpSession* pSession) { m_pSession = pSession ; }
hzEcode ProcessEvent (hzChain& Z) ;
hzEcode Storeform (const char* cpPath) ;
hzEcode SendRawChain (HttpRC hrc, hzMimetype type, const hzChain& Data, uint32_t nExpires, bool bZip) ;
hzEcode SendRawString (HttpRC hrc, hzMimetype type, const hzString& fixContent, uint32_t nExpires, bool bZip) ;
hzEcode SendFilePage (const char* pDir, const char* cpFilename, uint32_t nExpires, bool bZip) ;
hzEcode SendPageE (const char* pDir, const char* cpFilename, uint32_t nExpires, bool bZip) ;
hzEcode SendFileHead (const char* pDir, const char* cpFilename, uint32_t nExpires = 0) ;
hzEcode SendHttpHead (const hzString& fixContent, hzMimetype type, uint32_t nExpires = 0) ;
hzEcode SendHttpHead (const hzChain& fixContent, hzMimetype type, uint32_t nExpires = 0) ;
hzEcode Redirect (const hzUrl& url, uint32_t nExpires, bool bZip) ;
hzEcode SendNotFound (hzUrl& url) ;
hzEcode SendError (HttpRC hrc, const char* va_alist ...) ;
hzEcode SendAjaxResult (HttpRC hrc) ;
hzEcode SendAjaxResult (HttpRC hrc, const char* va_alist ...) ;
hzEcode SendAjaxResult (HttpRC hrc, hzChain& Z) ;
} ;
#endif // hzHttpServer_h