HTTP Server Reference
Multi-threaded HTTP/HTTPS/WebSocket server framework
Architecture
The EPL HTTP Server is a multi-threaded HTTP/HTTPS/WebSocket server supporting virtual hosting with multiple independent sites.
Key Files
| File | Purpose |
|---|---|
superserver.epl | Entry point - loads sites.json, initializes modules |
http_srv.epl | TServer class - thread pool management |
onaccept.epl | TOnAccept - HTTP parsing state machine |
action.epl | TAction - request dispatcher |
THTTP_Base.epl | Module base class |
THTTP_Module.epl | Extended base with template support |
TTemplOperator.epl | Template processing engine |
websocket.epl | WebSocket frame parsing |
Request Flow
Client Request
│
TServer::OnAccept() [threaded, one per connection]
│
TOnAccept [HTTP parsing state machine, steps 1-99]
│
ProcessHttpData() [matches virtual host by Host header]
│
TAction [creates request context, GET/POST params]
│
ProcessUri() [hash-based handler lookup]
│
Module Handler (THTTP_Base subclass)
│
SendResponse()
Configuration
Path Aliases (epl_cfg.epl)
AddPathItem("Projects", "/Work/Apps/v0002_11_08_2022/Projects");
AddPathItem("HttpSrv", "/Work/Apps/v0002_11_08_2022/HttpSrv");
AddPathItem("Studio", "/Work/Apps/v0002_11_08_2022/Projects/Studio");
Used in includes:
include_file "$Studio/ElastLib/main_inc.epl";
include_file "$HttpSrv/THTTP_Module.epl";
sites.json Structure
{
"HttpIps": ["0.0.0.0:80"],
"HttpsIps": ["0.0.0.0:443"],
"Sites": [{
"Uri": "example.com",
"RedirUri": "https://example.com",
"Dir": "$CUR_SCR_DIR/../MySite",
"Module": "$CUR_SCR_DIR/../MySite/THTTP_MySite.epl",
"Http": 1,
"Https": 1,
"WSockName": "wss://example.com",
"LandPage": "/index.html",
"RootDir": "$CUR_SCR_DIR/../MySite/content",
"DbPath": "$CUR_SCR_DIR/../MySite/main.orn",
"DbClasses": "$CUR_SCR_DIR/../MySite/Classes",
"DbLog": "$CUR_SCR_DIR/../MySite/log"
}]
}
SSL Certificates
Place in CertPath directory:
cert.pem- CA certificatechain.pem- Certificate chainfullchain.pem- Full certificate chainprivkey.pem- Private key
Module Development
Required Include Order
#define _STRINGOP_LIGHT
class TSem : public V_Semaphore{}
class TSem2 : public V_Semaphore{}
class TPack : public V_PackVariant{}
TSem @Sem;
include_file "$Projects/Studio/Sys/TStringOP.epl";
include_file "$Projects/Studio/ElastLib/TJson.epl";
include_file "$Projects/Studio/ElastLib/TProtocol.h";
include_file "$HttpSrv/THTTP_Module.epl";
Module Pattern
class THTTP_mysite : public THTTP_Module {
int TemplId;
int SymbolId;
}
THTTP_mysite @instance;
variant vCurModule = instance; // REQUIRED: server reads this
vCurModule->sGuid = "unique-guid"; // REQUIRED: unique identifier
virtual int THTTP_mysite::Prepare() {
LoadJson(); // Load act.json handlers
TemplOP->PrepareTemplate(TemplId, 2, "page.html");
SymbolId = TemplOP->GetSymbol("CONTENT");
return 1;
}
int THTTP_mysite::Handler(TAction ptr Action) {
variant LocArray;
apush(LocArray, SymbolId, "CONTENT", "value");
TemplOP->ProcessTemplate(TemplId, Action, LocArray, Action->OutText);
return 1;
}
TAction Properties
| Property | Description |
|---|---|
Action->GET["param"] | Query string parameters |
Action->POST["param"] | POST body parameters (or JSON) |
Action->Uri | Request path |
Action->Host | THost virtual host config |
Action->OutText | Set response content |
Action->isSocket | 1 if WebSocket request |
Action->PAccept->SendFile(path) | Send file download |
Action->PAccept->SendError(msg, code) | Send error response |
Action->PAccept->Redirect(url) | HTTP redirect |
Request Routing (act.json)
{
"Actions": [{
"Uri": "login",
"Function": "OnLogin",
"Flags": 1,
"Parms": [{
"Name": "email",
"Type": 1,
"Verify": 3,
"MinLim": 5,
"MaxLim": 100
}]
}]
}
Parameter Types
0=int, 1=string, 2=float, 3=object, 4=array
Verify Types
0=Int, 1=Login, 2=Password, 3=Email, 4=ItemName, 5=ItemText, 6=Float, 7=LongNote, 8=FileType, 14=Array, 15=Guid, 16=None
Flags
1=FLAG_ALLOWED_WITH_NO_AUTH, 2=FLAG_FILE_DOWNLOAD, 7=FLAG_ALLOWED_SIMPLE_ACTION, 8=FLAG_WBS_ACTION
Template Engine
Template Syntax
--VARIABLE--- Variable replacement**FunctionName**- Callback function++template++- Include sub-template
Example Template
<html>
<head><title>--TITLE--</title></head>
<body>
++header++
<main>
--CONTENT--
**RenderItems**
</main>
++footer++
</body>
</html>
Callback Signature
void THTTP_mysite::RenderItems(TAction ptr Action, int ptr Index, string ptr Output) {
Output = "<ul>";
for(int i=0; i<count(Items); i++){
Output .= "<li>" . Items[i] . "</li>";
}
Output .= "</ul>";
}
WebSocket
Module Virtual Methods
// Called when WebSocket connection initializes
virtual int THTTP_mysite::WS_OnInit(int ptr hSock, TSocketData ptr SocketData);
// Called for binary WebSocket frames (opcode 0x02)
virtual int THTTP_mysite::WS_OnBinaryData(int ptr hSock, BYTE *Buf, int ptr PLen, TSocketData ptr SocketData);
// Called for JSON text frames
virtual int THTTP_mysite::WS_OnJsonData(int ptr hSock, TAction ptr Action, TSocketData ptr SocketData);
TSocketData
class TSocketData {
int hSock; // Socket handle
TServer PServer; // Server reference
variant vObj; // TOnAccept instance
variant UserData; // Module-specific state
}
Sending Messages
// From TOnAccept (use PAccept)
Action->PAccept->SendWbsMessage(text); // Text frame
Action->PAccept->SendWbsMessageLL(Buf, Len, 1, 0); // Binary frame
// From TServer (use PServer)
PServer->WbsSend(hSock, text); // Text to specific socket
PServer->WbsSendBin(hSock, Buf, Len); // Binary to socket
WebSocket Opcodes
| Opcode | Meaning |
|---|---|
0x00 | Continuation frame |
0x01 | Text data |
0x02 | Binary data |
0x08 | Connection close |
0x09 | Ping |
0x0A | Pong |
Static File Routing
| URL Prefix | Source Directory |
|---|---|
/files/ | {RootDir}/files/ |
/pages/ | {RootDir}/pages/ |
/sb/ | {RootDir}/sb/ |
/js/ | {RootDir}/static/js/ |
/css/ | {RootDir}/static/css/ |
/static/ | {RootDir}/static/ |