22#include "RConfigure.h"
134 const char *jsrootsys =
gSystem->Getenv(
"JSROOTSYS");
136 jsrootsys =
gEnv->GetValue(
"HttpServ.JSRootPath", jsrootsys);
138 if (jsrootsys && *jsrootsys) {
139 if ((strncmp(jsrootsys,
"http://", 7)==0) || (strncmp(jsrootsys,
"https://", 8)==0))
146 TString jsdir = TString::Format(
"%s/js", TROOT::GetDataDir().Data());
147 if (gSystem->ExpandPathName(jsdir)) {
148 ::Warning(
"THttpServer::THttpServer",
"problems resolving '%s', set JSROOTSYS to proper JavaScript ROOT location",
156 Bool_t basic_sniffer = strstr(engine,
"basic_sniffer") !=
nullptr;
158 AddLocation(
"jsrootsys/", fJSROOTSYS.Data());
163 AddLocation(
"currentdir/",
".");
167 fDefaultPage = fJSROOTSYS +
"/files/online.htm";
168 fDrawPage = fJSROOTSYS +
"/files/draw.htm";
171 if (!basic_sniffer) {
173 if (snifferClass && snifferClass->
IsLoaded())
176 ::Warning(
"THttpServer::THttpServer",
"Fail to load TRootSnifferFull class, use basic functionality");
190 if (strchr(engine,
';') == 0) {
191 CreateEngine(engine);
197 if ((strcmp(opt,
"readonly") == 0) || (strcmp(opt,
"ro") == 0)) {
198 GetSniffer()->SetReadOnly(
kTRUE);
199 }
else if ((strcmp(opt,
"readwrite") == 0) || (strcmp(opt,
"rw") == 0)) {
200 GetSniffer()->SetReadOnly(
kFALSE);
201 }
else if (strcmp(opt,
"global") == 0) {
202 GetSniffer()->SetScanGlobalDir(
kTRUE);
203 }
else if (strcmp(opt,
"noglobal") == 0) {
204 GetSniffer()->SetScanGlobalDir(
kFALSE);
205 }
else if (strncmp(opt,
"cors=", 5) == 0) {
207 }
else if (strcmp(opt,
"cors") == 0) {
228 while (
auto engine =
dynamic_cast<THttpEngine *
>(iter()))
311 if (!prefix || (*prefix == 0))
334 fJSROOT = location ? location :
"";
347 if (!filename.empty())
366 if (!filename.empty())
401 const char *arg = strchr(engine,
':');
407 clname.
Append(engine, arg - engine);
412 if ((clname.
Length() == 0) || (clname ==
"http") || (clname ==
"civetweb")) {
415 }
else if (clname ==
"socket") {
421 }
else if (clname ==
"https") {
423 }
else if (clname ==
"fastcgi") {
475 Error(
"SetTimer",
"Server runs already in special thread, therefore no any timer can be created");
477 fTimer = std::make_unique<THttpTimer>(milliSec, mode, *
this);
501 std::thread thrd([
this] {
511 std::this_thread::sleep_for(std::chrono::milliseconds(1));
516 fThrd = std::move(thrd);
541 if (!fname || (*fname == 0))
549 const char *next = strpbrk(fname,
"/\\");
554 if ((next == fname + 2) && (*fname ==
'.') && (*(fname + 1) ==
'.')) {
563 if ((next == fname + 1) && (*fname ==
'.')) {
591 if (!uri || (*uri == 0))
600 fname.
Remove(0, pos + (entry.first.length() - 1));
603 res = entry.second.c_str();
604 if ((fname[0] ==
'/') && (res[res.
Length() - 1] ==
'/'))
633 std::unique_lock<std::mutex> lk(
fMutex);
634 arg->fNotifyFlag =
kFALSE;
663 arg->NotifyCondition();
668 std::unique_lock<std::mutex> lk(
fMutex);
689 Warning(
"ProcessRequests",
"Changing main thread to %ld", (
long)
id);
709 std::unique_lock<std::mutex> lk(
fMutex, std::defer_lock);
713 std::shared_ptr<THttpCallArg> arg;
716 if (!
fArgs.empty()) {
725 if (arg->fFileName ==
"root_batch_holder.js") {
730 auto prev =
fSniffer->SetCurrentCallArg(arg.get());
740 arg->NotifyCondition();
745 while (
auto engine =
static_cast<THttpEngine *
>(iter())) {
776 auto wsptr =
FindWS(arg->GetPathName());
778 if (!wsptr || !wsptr->ProcessBatchHolder(arg)) {
780 arg->NotifyCondition();
790 std::string arr =
"[";
793 std::lock_guard<std::mutex> grd(
fWSMutex);
795 if (arr.length() > 1)
798 arr.append(
TString::Format(
"{ name: \"%s\", title: \"%s\" }", ws->GetName(), ws->GetTitle()).Data());
806 std::string arg =
"\"$$$wslist$$$\"";
808 auto pos = res.find(arg);
809 if (pos != std::string::npos)
810 res.replace(pos, arg.length(), arr);
824 const std::string place_holder =
"<!--jsroot_importmap-->";
826 auto p = arg->fContent.find(place_holder);
828 bool old_format = (p == std::string::npos);
832 if (arg->fPathName.Length() > 0)
834 for (
Int_t n = 1;
n < arg->fPathName.Length()-1; ++
n)
835 if (arg->fPathName[
n] ==
'/') {
836 if (arg->fPathName[
n-1] !=
'/') {
848 if (!version.empty()) {
850 std::string search =
"from './jsrootsys/";
851 std::string replace =
"from './" + version +
"/jsrootsys/";
852 arg->ReplaceAllinContent(search, replace);
854 search =
"from './rootui5sys/";
855 replace =
"from './" + version +
"/rootui5sys/";
856 arg->ReplaceAllinContent(search, replace);
858 search =
"jsrootsys/scripts/JSRoot.core.";
859 replace = version +
"/jsrootsys/scripts/JSRoot.core.";
860 arg->ReplaceAllinContent(search, replace,
true);
861 arg->AddNoCacheHeader();
869 if (repl.back() !=
'/')
874 while (slash_cnt-- > 0) repl.append(
"../");
875 repl.append(
"jsrootsys/");
880 arg->ReplaceAllinContent(
"=\"jsrootsys/", repl);
881 arg->ReplaceAllinContent(
"from './jsrootsys/",
TString::Format(
"from '%s", repl.substr(2).c_str()).Data());
886 std::string path_prefix, jsroot_prefix;
889 while (slash_cnt-- > 0)
890 path_prefix.append(
"../");
895 if (!version.empty())
896 path_prefix.append(version +
"/");
899 jsroot_prefix =
fJSROOT.Data();
900 if (jsroot_prefix.back() !=
'/')
901 jsroot_prefix.append(
"/");
903 jsroot_prefix = path_prefix +
"jsrootsys/";
906 static std::map<std::string, std::string> modules = {
907 {
"jsroot",
"main.mjs"}, {
"jsroot/core",
"core.mjs"},
908 {
"jsroot/io",
"io.mjs"}, {
"jsroot/tree",
"tree.mjs"},
909 {
"jsroot/draw",
"draw.mjs"}, {
"jsroot/gui",
"gui.mjs"},
910 {
"jsroot/d3",
"d3.mjs"}, {
"jsroot/three",
"three.mjs"}, {
"jsroot/three_addons",
"three_addons.mjs"},
911 {
"jsroot/geom",
"geom/TGeoPainter.mjs"}, {
"jsroot/hpainter",
"gui/HierarchyPainter.mjs"},
912 {
"jsroot/webwindow",
"webwindow.mjs"}
917 while ((--pspace > 0) && (arg->fContent[pspace] ==
' ') && (space_prefix.
Length() < 20))
921 TString importmap =
"<script type=\"importmap\">\n";
922 importmap += space_prefix +
"{\n";
923 importmap += space_prefix +
" \"imports\": ";
924 for (
auto &entry : modules) {
925 importmap.
Append(
TString::Format(
"%s\n%s \"%s\": \"%smodules/%s\"", first ?
"{" :
",", space_prefix.
Data(), entry.first.c_str(), jsroot_prefix.c_str(), entry.second.c_str()));
931 if (entry.first !=
"jsrootsys/")
932 importmap.
Append(
TString::Format(
",\n%s \"%s\": \"%s%s\"", space_prefix.
Data(), entry.first.c_str(), path_prefix.c_str(), entry.first.c_str()));
934 importmap.
Append(space_prefix +
" }\n");
935 importmap.
Append(space_prefix +
"}\n");
936 importmap.
Append(space_prefix +
"</script>\n");
938 arg->fContent.erase(p, place_holder.length());
940 arg->fContent.insert(p, importmap.
Data());
957 if ((arg->fFileName ==
"root.websocket") || (arg->fFileName ==
"root.longpoll")) {
962 if (arg->fFileName.IsNull() || (arg->fFileName ==
"index.htm") || (arg->fFileName ==
"default.htm")) {
966 if (arg->fFileName ==
"default.htm") {
972 auto wsptr =
FindWS(arg->GetPathName());
974 auto handler = wsptr.get();
981 arg->fContent = handler->GetDefaultPageContent().Data();
983 if (arg->fContent.find(
"file:") == 0) {
984 const char *fname = arg->fContent.c_str() + 5;
990 version = handler->GetCodeVersion();
992 handler->VerifyDefaultPageContent(arg);
996 if (arg->fContent.empty() && arg->fFileName.IsNull() && arg->fPathName.IsNull() &&
IsWSOnly()) {
1001 arg->SetContent(
"refused");
1005 if (arg->fContent.empty() && !
IsWSOnly()) {
1013 if (arg->fContent.empty()) {
1016 }
else if (!arg->Is404()) {
1020 const char *hjsontag =
"\"$$$h.json$$$\"";
1023 if (arg->fContent.find(hjsontag) != std::string::npos) {
1026 const char *topname =
fTopName.Data();
1027 if (arg->fTopName.Length() > 0)
1028 topname = arg->fTopName.Data();
1029 fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);
1031 arg->ReplaceAllinContent(hjsontag, h_json.
Data());
1033 arg->AddNoCacheHeader();
1035 if (arg->fQuery.Index(
"nozip") ==
kNPOS)
1038 arg->SetContentType(
"text/html");
1043 if ((arg->fFileName ==
"draw.htm") && !
IsWSOnly()) {
1050 const char *rootjsontag =
"\"$$$root.json$$$\"";
1051 const char *hjsontag =
"\"$$$h.json$$$\"";
1057 if ((arg->fQuery.Index(
"no_h_json") ==
kNPOS) && (arg->fQuery.Index(
"webcanvas") ==
kNPOS) &&
1058 (arg->fContent.find(hjsontag) != std::string::npos)) {
1061 const char *topname =
fTopName.Data();
1062 if (arg->fTopName.Length() > 0)
1063 topname = arg->fTopName.Data();
1064 fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store,
kTRUE);
1066 arg->ReplaceAllinContent(hjsontag, h_json.
Data());
1069 if ((arg->fQuery.Index(
"no_root_json") ==
kNPOS) && (arg->fQuery.Index(
"webcanvas") ==
kNPOS) &&
1070 (arg->fContent.find(rootjsontag) != std::string::npos)) {
1072 if (
fSniffer->Produce(arg->fPathName.Data(),
"root.json",
"compact=23", str))
1073 arg->ReplaceAllinContent(rootjsontag, str);
1075 arg->AddNoCacheHeader();
1076 if (arg->fQuery.Index(
"nozip") ==
kNPOS)
1078 arg->SetContentType(
"text/html");
1083 if ((arg->fFileName ==
"favicon.ico") && arg->fPathName.IsNull()) {
1084 arg->SetFile(
fJSROOTSYS +
"/img/RootIcon.ico");
1090 arg->SetFile(filename);
1095 if (!arg->fPathName.IsNull() && !arg->fFileName.IsNull()) {
1096 TString wsname = arg->fPathName, fname;
1097 auto pos = wsname.
First(
'/');
1099 wsname = arg->fPathName;
1101 wsname = arg->fPathName(0, pos);
1102 fname = arg->fPathName(pos + 1, arg->fPathName.Length() - pos);
1106 fname.Append(arg->fFileName);
1112 if (ws && ws->CanServeFiles()) {
1113 TString fdir = ws->GetDefaultPageContent();
1115 if (fdir.
Index(
"file:") == 0) {
1117 auto separ = fdir.
Last(
'/');
1131 filename = arg->fFileName;
1140 if (arg->fContent.empty())
1142 }
else if ((filename ==
"h.xml") || (filename ==
"get.xml")) {
1143 Bool_t compact = arg->fQuery.Index(
"compact") !=
kNPOS,
1147 res.
Form(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
1155 auto len0 = res.
Length();
1156 const char *topname =
fTopName.Data();
1157 if (arg->fTopName.Length() > 0)
1158 topname = arg->fTopName.Data();
1159 fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store, filename ==
"get.xml");
1160 processed = res.
Length() > len0;
1167 arg->SetContent(std::string(res.
Data()));
1171 }
else if (filename ==
"h.json") {
1174 const char *topname =
fTopName.Data();
1175 if (arg->fTopName.Length() > 0)
1176 topname = arg->fTopName.Data();
1177 fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);
1180 arg->SetContent(std::string(res.
Data()));
1184 }
else if (
fSniffer->Produce(arg->fPathName.Data(), filename.
Data(), arg->fQuery.Data(), arg->fContent)) {
1198 if (filename ==
"root.bin") {
1201 const char *parname =
fSniffer->IsStreamerInfoItem(arg->fPathName.Data()) ?
"BVersion" :
"MVersion";
1206 arg->AddNoCacheHeader();
1210 arg->AddHeader(
"Access-Control-Allow-Origin",
GetCors());
1213 arg->AddHeader(
"Access-Control-Expose-Headers",
"Content-Range, Content-Length, Date");
1214 arg->AddHeader(
"Access-Control-Allow-Methods",
"GET, HEAD, OPTIONS");
1225 return fSniffer->RegisterObject(subfolder, obj);
1235 return fSniffer->UnregisterObject(obj);
1245 std::lock_guard<std::mutex> grd(
fWSMutex);
1254 std::lock_guard<std::mutex> grd(
fWSMutex);
1267 std::lock_guard<std::mutex> grd(
fWSMutex);
1269 if (strcmp(
name, ws->GetName()) == 0)
1286 auto wsptr =
FindWS(arg->GetPathName());
1288 auto handler = wsptr.get();
1290 if (!handler && !external_thrd)
1293 if (external_thrd && (!handler || !handler->AllowMTProcess())) {
1295 std::unique_lock<std::mutex> lk(
fMutex);
1299 arg->fCond.wait(lk);
1311 if (arg->fFileName ==
"root.websocket") {
1313 process = handler->HandleWS(arg);
1314 }
else if (arg->fFileName ==
"root.longpoll") {
1316 if (arg->fQuery.BeginsWith(
"raw_connect") || arg->fQuery.BeginsWith(
"txt_connect")) {
1319 arg->SetMethod(
"WS_CONNECT");
1321 bool israw = arg->fQuery.BeginsWith(
"raw_connect");
1326 if (handler->HandleWS(arg)) {
1327 arg->SetMethod(
"WS_READY");
1329 if (handler->HandleWS(arg))
1330 arg->SetTextContent(std::string(israw ?
"txt:" :
"") + std::to_string(arg->GetWSId()));
1332 arg->TakeWSEngine();
1335 process = arg->IsText();
1342 arg->SetWSId(std::stoul(connid));
1344 arg->SetMethod(
"WS_CLOSE");
1345 arg->SetTextContent(
"OK");
1347 arg->SetMethod(
"WS_DATA");
1350 process = handler->HandleWS(arg);
1409 return fSniffer->RegisterCommand(cmdname, method, icon);
1417 return SetItemField(foldername,
"_hidden", hide ?
"true" : (
const char *)0);
1436 return fSniffer->CreateItem(fullname, title);
1460 static const struct {
1465 {
".json", 5,
"application/json"},
1466 {
".bin", 4,
"application/x-binary"},
1467 {
".gif", 4,
"image/gif"},
1468 {
".jpg", 4,
"image/jpeg"},
1469 {
".png", 4,
"image/png"},
1470 {
".html", 5,
"text/html"},
1471 {
".htm", 4,
"text/html"},
1472 {
".shtm", 5,
"text/html"},
1473 {
".shtml", 6,
"text/html"},
1474 {
".css", 4,
"text/css"},
1475 {
".js", 3,
"application/x-javascript"},
1476 {
".mjs", 4,
"text/javascript"},
1477 {
".ico", 4,
"image/x-icon"},
1478 {
".jpeg", 5,
"image/jpeg"},
1479 {
".svg", 4,
"image/svg+xml"},
1480 {
".txt", 4,
"text/plain"},
1481 {
".torrent", 8,
"application/x-bittorrent"},
1482 {
".wav", 4,
"audio/x-wav"},
1483 {
".mp3", 4,
"audio/x-mp3"},
1484 {
".mid", 4,
"audio/mid"},
1485 {
".m3u", 4,
"audio/x-mpegurl"},
1486 {
".ogg", 4,
"application/ogg"},
1487 {
".ram", 4,
"audio/x-pn-realaudio"},
1488 {
".xslt", 5,
"application/xml"},
1489 {
".xsl", 4,
"application/xml"},
1490 {
".ra", 3,
"audio/x-pn-realaudio"},
1491 {
".doc", 4,
"application/msword"},
1492 {
".exe", 4,
"application/octet-stream"},
1493 {
".zip", 4,
"application/x-zip-compressed"},
1494 {
".xls", 4,
"application/excel"},
1495 {
".tgz", 4,
"application/x-tar-gz"},
1496 {
".tar", 4,
"application/x-tar"},
1497 {
".gz", 3,
"application/x-gunzip"},
1498 {
".arj", 4,
"application/x-arj-compressed"},
1499 {
".rar", 4,
"application/x-arj-compressed"},
1500 {
".rtf", 4,
"application/rtf"},
1501 {
".pdf", 4,
"application/pdf"},
1502 {
".swf", 4,
"application/x-shockwave-flash"},
1503 {
".mpg", 4,
"video/mpeg"},
1504 {
".webm", 5,
"video/webm"},
1505 {
".mpeg", 5,
"video/mpeg"},
1506 {
".mov", 4,
"video/quicktime"},
1507 {
".mp4", 4,
"video/mp4"},
1508 {
".m4v", 4,
"video/x-m4v"},
1509 {
".asf", 4,
"video/x-ms-asf"},
1510 {
".avi", 4,
"video/x-msvideo"},
1511 {
".bmp", 4,
"image/bmp"},
1512 {
".ttf", 4,
"application/x-font-ttf"},
1513 {
".woff", 5,
"font/woff"},
1514 {
".woff2", 6,
"font/woff2"},
1517 int path_len = strlen(path);
1528 return "text/plain";
1540 std::ifstream is(filename, std::ios::in | std::ios::binary);
1544 is.seekg(0, is.end);
1546 is.seekg(0, is.beg);
1548 char *buf = (
char *)
malloc(len);
1564 std::ifstream is(filename, std::ios::in | std::ios::binary);
1567 is.seekg(0, std::ios::end);
1568 res.resize(is.tellg());
1569 is.seekg(0, std::ios::beg);
1570 is.read((
char *)res.data(), res.length());
int Int_t
Signed integer 4 bytes (int).
int Ssiz_t
String size (currently int).
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
bool Bool_t
Boolean (0=false, 1=true) (bool).
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
static const struct @243147061004330160235326056313274363054075327066 builtin_mime_types[]
THttpEngine implementation, based on civetweb embedded server.
TClass instances represent classes, structs and namespaces in the ROOT type system.
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
THttpEngine implementation, based on fastcgi package.
Contains arguments for single HTTP call.
void Set404()
mark reply as 404 error - page/request not exists or refused
Abstract class for implementing http protocol for THttpServer.
void SetServer(THttpServer *serv)
virtual Bool_t Create(const char *)
Method to create all components of engine.
Emulation of websocket with long poll requests.
Online http server for arbitrary ROOT application.
Bool_t IsReadOnly() const
returns read-only mode
Bool_t RegisterCommand(const char *cmdname, const char *method, const char *icon=nullptr)
Register command which can be executed from web interface.
TString fJSROOT
! location of external JSROOT files
virtual void ProcessRequest(std::shared_ptr< THttpCallArg > arg)
Process single http request.
std::shared_ptr< THttpWSHandler > FindWS(const char *name)
Find web-socket handler with given name.
std::unique_ptr< TRootSniffer > fSniffer
! sniffer provides access to ROOT objects hierarchy
void SetTimer(Long_t milliSec=100, Bool_t mode=kTRUE)
Create timer which will invoke ProcessRequests() function periodically.
virtual void ProcessBatchHolder(std::shared_ptr< THttpCallArg > &arg)
Process special http request for root_batch_holder.js script.
std::vector< std::shared_ptr< THttpWSHandler > > fWSHandlers
! list of WS handlers
virtual ~THttpServer()
destructor
void SetTerminate()
set termination flag, no any further requests will be processed
virtual void MissedRequest(THttpCallArg *arg)
Method called when THttpServer cannot process request.
Bool_t fOwnThread
! true when specialized thread allocated for processing requests
void SetSniffer(TRootSniffer *sniff)
Set TRootSniffer to the server.
Bool_t IsFileRequested(const char *uri, TString &res) const
Check if file is requested, thread safe.
void SetReadOnly(Bool_t readonly=kTRUE)
Set read-only mode for the server (default on).
const char * GetItemField(const char *fullname, const char *name)
Get item field from sniffer.
const char * GetCors() const
Returns specified CORS domain.
std::thread fThrd
! own thread
void StopServerThread()
Stop server thread.
Int_t ProcessRequests()
Process submitted requests, must be called from appropriate thread.
Bool_t ExecuteWS(std::shared_ptr< THttpCallArg > &arg, Bool_t external_thrd=kFALSE, Bool_t wait_process=kFALSE)
Execute WS request.
void RegisterWS(std::shared_ptr< THttpWSHandler > ws)
Register WS handler.
Long_t fProcessingThrdId
! id of the thread where events are recently processing
TString fTopName
! name of top folder, default - "ROOT"
void SetDrawPage(const std::string &filename="")
Set drawing HTML page.
Bool_t CreateItem(const char *fullname, const char *title)
Create item in sniffer.
Bool_t ExecuteHttp(std::shared_ptr< THttpCallArg > arg)
Execute HTTP request.
Bool_t Hide(const char *fullname, Bool_t hide=kTRUE)
Hides folder or element from web gui.
Bool_t IsCorsCredentials() const
Returns kTRUE if Access-Control-Allow-Credentials header should be used.
void AddLocation(const char *prefix, const char *path)
Add files location, which could be used in the server.
std::map< std::string, std::string > fLocations
! list of local directories, which could be accessed via server
Bool_t SubmitHttp(std::shared_ptr< THttpCallArg > arg, Bool_t can_run_immediately=kFALSE)
Submit HTTP request.
Long_t fMainThrdId
! id of the thread for processing requests
TString fJSROOTSYS
! location of local JSROOT files
std::unique_ptr< THttpTimer > fTimer
! timer used to access main thread
Bool_t fWSOnly
! when true, handle only websockets / longpoll engine
Bool_t Register(const char *subfolder, TObject *obj)
Register object in subfolder.
TList fEngines
! engines which runs http server
Bool_t IsCors() const
Returns kTRUE if CORS was configured.
const char * GetCorsCredentials() const
Returns specified CORS credentials value - if any.
std::queue< std::shared_ptr< THttpCallArg > > fArgs
! submitted arguments
void SetDefaultPage(const std::string &filename="")
Set default HTML page.
THttpServer(const THttpServer &)=delete
static char * ReadFileContent(const char *filename, Int_t &len)
Reads content of file from the disk.
void CreateServerThread()
Creates special thread to process all requests, directed to http server.
std::string fDrawPageCont
! content of draw html page
Bool_t Unregister(TObject *obj)
Unregister object.
void SetWSOnly(Bool_t on=kTRUE)
Set websocket-only mode.
std::string BuildWSEntryPage()
Create summary page with active WS handlers.
Bool_t IsWSOnly() const
returns true if only websockets are handled by the server
std::mutex fWSMutex
! mutex to protect WS handler lists
virtual Bool_t CreateEngine(const char *engine)
Factory method to create different http engines.
Bool_t SetIcon(const char *fullname, const char *iconname)
Set name of icon, used in browser together with the item.
std::string fDrawPage
! file name for drawing of single element
std::string fDefaultPageCont
! content of default html page
static Bool_t VerifyFilePath(const char *fname)
Checked that filename does not contains relative path below current directory.
Bool_t SetItemField(const char *fullname, const char *name, const char *value)
Set item field in sniffer.
void SetJSROOT(const char *location)
Set location of JSROOT to use with the server.
std::mutex fMutex
! mutex to protect list with arguments
std::string fDefaultPage
! file name for default page name
void UnregisterWS(std::shared_ptr< THttpWSHandler > ws)
Unregister WS handler.
static const char * GetMimeType(const char *path)
Guess mime type base on file extension.
void ReplaceJSROOTLinks(std::shared_ptr< THttpCallArg > &arg, const std::string &version="")
Replaces all references like "jsrootsys/..." or other pre-configured pathes.
Bool_t fTerminated
! termination flag, disables all requests processing
void Restrict(const char *path, const char *options)
Restrict access to specified object.
void Timeout() override
timeout handler used to process http requests in main ROOT thread
THttpTimer(Long_t milliSec, Bool_t mode, THttpServer &serv)
!< server processing requests
Class for user-side handling of websocket with THttpServer.
TObject * At(Int_t idx) const override
Int_t GetLast() const override
Return index of last object in array.
virtual const char * GetName() const
Returns name of object.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
TObject()
TObject constructor.
static const TString & GetRootSys()
Get the rootsys directory in the installation. Static utility function.
static const TString & GetDataDir()
Get the data directory in the installation. Static utility function.
Storage of hierarchy scan in TRootSniffer in JSON format.
Storage of hierarchy scan in TRootSniffer in XML format.
Sniffer of ROOT objects, data provider for THttpServer.
void CreateOwnTopFolder()
Create own TFolder structures independent from gROOT This allows to have many independent TRootSniffe...
void SetScanGlobalDir(Bool_t on=kTRUE)
When enabled (default), sniffer scans gROOT for files, canvases, histograms.
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Ssiz_t First(char c) const
Find first occurrence of a character c.
const char * Data() const
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Ssiz_t Last(char c) const
Find last occurrence of a character c.
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
TString & Remove(Ssiz_t pos)
TString & Append(const char *cs)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
static Long_t SelfId()
Static method returning the id for the current thread.
TTimer(const TTimer &)=delete
This class represents a WWW compatible URL.
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
void SetOptions(const char *opt)
void ParseOptions() const
Parse URL options into a key/value map.
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.