21 #include "RConfigure.h" 50 class THttpTimer :
public TTimer {
59 virtual void Timeout() { fServer.ProcessRequests(); }
147 Warning(
"THttpServer",
"problems resolving '%s', use JSROOTSYS to specify $ROOTSYS/etc/http location",
163 if (strstr(engine,
"basic_sniffer")) {
166 sniff = (
TRootSniffer *)
gROOT->ProcessLineSync(
"new TRootSnifferFull(\"sniff\");");
174 if (strchr(engine,
';') == 0) {
181 if ((strcmp(opt,
"readonly") == 0) || (strcmp(opt,
"ro") == 0)) {
183 }
else if ((strcmp(opt,
"readwrite") == 0) || (strcmp(opt,
"rw") == 0)) {
185 }
else if (strcmp(opt,
"global") == 0) {
187 }
else if (strcmp(opt,
"noglobal") == 0) {
189 }
else if (strncmp(opt,
"cors=", 5) == 0) {
191 }
else if (strcmp(opt,
"cors") == 0) {
214 std::unique_lock<std::mutex> lk(
fMutex);
220 owner = opt && !strcmp(opt,
"owner");
227 while ((engine = (
THttpEngine *)iter()) !=
nullptr)
285 if (!prefix || (*prefix == 0))
305 fJSROOT = location ? location :
"";
316 if (!filename.empty())
333 if (!filename.empty())
357 const char *arg = strchr(engine,
':');
363 clname.
Append(engine, arg - engine);
367 if ((clname.
Length() == 0) || (clname ==
"http") || (clname ==
"civetweb")) {
369 }
else if (clname ==
"https") {
371 }
else if (clname ==
"fastcgi") {
388 if (!eng->
Create(arg + 1)) {
422 fTimer =
new THttpTimer(milliSec, mode, *
this);
433 if (!fname || (*fname == 0))
438 while (*fname != 0) {
441 const char *next = strpbrk(fname,
"/\\");
446 if ((next == fname + 2) && (*fname ==
'.') && (*(fname + 1) ==
'.')) {
455 if ((next == fname + 1) && (*fname ==
'.')) {
482 if (!uri || (*uri == 0))
491 fname.
Remove(0, pos + (iter->first.length() - 1));
494 res = iter->second.c_str();
495 if ((fname[0] ==
'/') && (res[res.
Length() - 1] ==
'/'))
509 Bool_t THttpServer::ExecuteHttp(std::shared_ptr<THttpCallArg> arg)
523 std::unique_lock<std::mutex> lk(
fMutex);
551 std::unique_lock<std::mutex> lk(
fMutex);
582 arg->NotifyCondition();
589 std::unique_lock<std::mutex> lk(
fMutex);
591 fArgs.push(std::shared_ptr<THttpCallArg>(arg));
608 Bool_t THttpServer::SubmitHttp(std::shared_ptr<THttpCallArg> arg,
Bool_t can_run_immediately)
615 arg->NotifyCondition();
620 std::unique_lock<std::mutex> lk(
fMutex);
631 void THttpServer::ProcessRequests()
637 Error(
"ProcessRequests",
"Should be called only from main ROOT thread");
641 std::unique_lock<std::mutex> lk(
fMutex, std::defer_lock);
645 std::shared_ptr<THttpCallArg> arg;
648 if (!
fArgs.empty()) {
666 arg->NotifyCondition();
692 arg->NotifyCondition();
698 while ((engine = (
THttpEngine *)iter()) !=
nullptr) {
727 if ((arg->fFileName !=
"root.websocket") && (arg->fFileName !=
"root.longpoll"))
737 if (arg->fFileName ==
"root.websocket") {
739 if (!handler->HandleWS(arg))
741 }
else if (arg->fFileName ==
"root.longpoll") {
743 if ((arg->fQuery ==
"connect") || (arg->fQuery ==
"connect_raw")) {
746 arg->SetMethod(
"WS_CONNECT");
748 bool israw = (arg->fQuery ==
"connect_raw");
753 if (handler->HandleWS(arg)) {
754 arg->SetMethod(
"WS_READY");
756 if (handler->HandleWS(arg))
757 arg->SetTextContent(std::string(israw ?
"txt:" :
"") + std::to_string(arg->GetWSId()));
768 arg->SetWSId((
UInt_t)connid);
770 arg->SetMethod(
"WS_CLOSE");
771 arg->SetTextContent(
"OK");
773 arg->SetMethod(
"WS_DATA");
776 if (!handler->HandleWS(arg))
806 if (arg->
fContent.find(
"file:") == 0) {
827 std::string repl(
"=\"");
829 if (repl.back() !=
'/')
834 const char *hjsontag =
"\"$$$h.json$$$\"";
837 if (arg->
fContent.find(hjsontag) != std::string::npos) {
848 "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
864 const char *rootjsontag =
"\"$$$root.json$$$\"";
865 const char *hjsontag =
"\"$$$h.json$$$\"";
871 std::string repl(
"=\"");
873 if (repl.back() !=
'/')
879 (arg->
fContent.find(hjsontag) != std::string::npos)) {
891 (arg->
fContent.find(rootjsontag) != std::string::npos)) {
897 "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
923 if ((filename ==
"h.xml") || (filename ==
"get.xml")) {
929 res.
Form(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
951 }
else if (filename ==
"h.json") {
974 if (filename ==
"root.bin") {
983 "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
995 Bool_t THttpServer::Register(
const char *subfolder,
TObject *obj)
1048 Bool_t THttpServer::RegisterCommand(
const char *cmdname,
const char *method,
const char *icon)
1056 Bool_t THttpServer::Hide(
const char *foldername,
Bool_t hide)
1058 return SetItemField(foldername,
"_hidden", hide ?
"true" : (
const char *)0);
1067 Bool_t THttpServer::SetIcon(
const char *fullname,
const char *iconname)
1069 return SetItemField(fullname,
"_icon", iconname);
1074 Bool_t THttpServer::CreateItem(
const char *fullname,
const char *title)
1081 Bool_t THttpServer::SetItemField(
const char *fullname,
const char *
name,
const char *value)
1088 const char *THttpServer::GetItemField(
const char *fullname,
const char *name)
1096 const char *THttpServer::GetMimeType(
const char *path)
1098 static const struct {
1103 {
".json", 5,
"application/json"},
1104 {
".bin", 4,
"application/x-binary"},
1105 {
".gif", 4,
"image/gif"},
1106 {
".jpg", 4,
"image/jpeg"},
1107 {
".png", 4,
"image/png"},
1108 {
".html", 5,
"text/html"},
1109 {
".htm", 4,
"text/html"},
1110 {
".shtm", 5,
"text/html"},
1111 {
".shtml", 6,
"text/html"},
1112 {
".css", 4,
"text/css"},
1113 {
".js", 3,
"application/x-javascript"},
1114 {
".ico", 4,
"image/x-icon"},
1115 {
".jpeg", 5,
"image/jpeg"},
1116 {
".svg", 4,
"image/svg+xml"},
1117 {
".txt", 4,
"text/plain"},
1118 {
".torrent", 8,
"application/x-bittorrent"},
1119 {
".wav", 4,
"audio/x-wav"},
1120 {
".mp3", 4,
"audio/x-mp3"},
1121 {
".mid", 4,
"audio/mid"},
1122 {
".m3u", 4,
"audio/x-mpegurl"},
1123 {
".ogg", 4,
"application/ogg"},
1124 {
".ram", 4,
"audio/x-pn-realaudio"},
1125 {
".xslt", 5,
"application/xml"},
1126 {
".xsl", 4,
"application/xml"},
1127 {
".ra", 3,
"audio/x-pn-realaudio"},
1128 {
".doc", 4,
"application/msword"},
1129 {
".exe", 4,
"application/octet-stream"},
1130 {
".zip", 4,
"application/x-zip-compressed"},
1131 {
".xls", 4,
"application/excel"},
1132 {
".tgz", 4,
"application/x-tar-gz"},
1133 {
".tar", 4,
"application/x-tar"},
1134 {
".gz", 3,
"application/x-gunzip"},
1135 {
".arj", 4,
"application/x-arj-compressed"},
1136 {
".rar", 4,
"application/x-arj-compressed"},
1137 {
".rtf", 4,
"application/rtf"},
1138 {
".pdf", 4,
"application/pdf"},
1139 {
".swf", 4,
"application/x-shockwave-flash"},
1140 {
".mpg", 4,
"video/mpeg"},
1141 {
".webm", 5,
"video/webm"},
1142 {
".mpeg", 5,
"video/mpeg"},
1143 {
".mov", 4,
"video/quicktime"},
1144 {
".mp4", 4,
"video/mp4"},
1145 {
".m4v", 4,
"video/x-m4v"},
1146 {
".asf", 4,
"video/x-ms-asf"},
1147 {
".avi", 4,
"video/x-msvideo"},
1148 {
".bmp", 4,
"image/bmp"},
1149 {
".ttf", 4,
"application/x-font-ttf"},
1152 int path_len = strlen(path);
1163 return "text/plain";
1169 char *THttpServer::ReadFileContent(
const char *filename,
Int_t &len)
1173 std::ifstream is(filename);
1177 is.seekg(0, is.end);
1179 is.seekg(0, is.beg);
1181 char *buf = (
char *)
malloc(len);
1195 std::string THttpServer::ReadFileContent(
const std::string &filename)
1197 std::ifstream is(filename);
1200 is.seekg(0, std::ios::end);
1201 res.resize(is.tellg());
1202 is.seekg(0, std::ios::beg);
1203 is.read((
char *)res.data(), res.length());
Bool_t RegisterObject(const char *subfolder, TObject *obj)
Register object in subfolder structure subfolder parameter can have many levels like: ...
virtual Bool_t IsStreamerInfoItem(const char *)
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
std::string fDrawPageCont
! content of draw html page
virtual void Process()
Method regularly called in main ROOT context.
void ReplaceAllinContent(const std::string &from, const std::string &to)
Replace all occurrences of.
Bool_t IsReadOnly() const
Returns readonly mode.
void SetDrawPage(const std::string &filename="")
Set file name of HTML page, delivered by the server when objects drawing page is requested from the b...
Storage of hierarchy scan in TRootSniffer in JSON format.
This class represents a WWW compatible URL.
TString & ReplaceAll(const TString &s1, const TString &s2)
virtual void MissedRequest(THttpCallArg *arg)
Method called when THttpServer cannot process request By default such requests replied with 404 code ...
Bool_t IsReadOnly() const
returns read-only mode
virtual void ProcessRequest(std::shared_ptr< THttpCallArg > arg)
Process single http request Depending from requested path and filename different actions will be perf...
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Bool_t IsCors() const
Returns kTRUE if CORS was configured.
TString fQuery
! additional arguments
TString fTopName
! name of top folder, default - "ROOT"
void SetDefaultPage(const std::string &filename="")
Set file name of HTML page, delivered by the server when http address is opened in the browser...
static const TString & GetRootSys()
Get the rootsys directory in the installation. Static utility function.
void Restrict(const char *path, const char *options)
Restrict access to the specified location.
Bool_t UnregisterObject(TObject *obj)
unregister (remove) object from folders structures folder itself will remain even when it will be emp...
TList fEngines
! engines which runs http server
TObject * At(Int_t idx) const
void SetServer(THttpServer *serv)
Bool_t fTerminated
! termination flag, disables all requests processing
void SetFile(const char *filename=nullptr)
indicate that http request should response with file content
void SetContentType(const char *typ)
set content type like "text/xml" or "application/json"
Bool_t CreateItem(const char *fullname, const char *title)
create item element
void SetContent(const char *cont)
Set content as text.
TRootSniffer * fSniffer
! sniffer provides access to ROOT objects hierarchy
THttpServer(const char *engine="civetweb:8080")
constructor
std::queue< std::shared_ptr< THttpCallArg > > fArgs
! submitted arguments
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
void SetTerminate()
set termination flag, no any further requests will be processed
Bool_t SetItemField(const char *fullname, const char *name, const char *value)
set field for specified item
The TNamed class is the base class for all named ROOT classes.
THttpTimer * fTimer
! timer used to access main thread
virtual const char * Getenv(const char *env)
Get environment variable.
TString fPathName
! item path
void Set404()
mark reply as 404 error - page/request not exists or refused
TString & Append(const char *cs)
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
static Long_t SelfId()
Static method returning the id for the current thread.
void SetCors(const std::string &domain="*")
Enable CORS header to ProcessRequests() responses Specified location (typically "*") add as "Access-C...
virtual ULong_t GetStreamerInfoHash()
void SetTimer(Long_t milliSec=100, Bool_t mode=kTRUE)
create timer which will invoke ProcessRequests() function periodically Timer is required to perform a...
TString fJSROOTSYS
! location of local JSROOT files
Storage of hierarchy scan in TRootSniffer in XML format.
void SetReadOnly(Bool_t readonly)
Set read-only mode for the server (default on) In read-only server is not allowed to change any ROOT ...
TString fTopName
! top item name
Int_t GetLast() const
Return index of last object in array.
void SetJson()
Set content type as "application/json".
Bool_t CreateEngine(const char *engine)
factory method to create different http engines At the moment two engine kinds are supported: civetwe...
std::string fDrawPage
! file name for drawing of single element
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
R__EXTERN TSystem * gSystem
std::map< std::string, std::string > fLocations
! list of local directories, which could be accessed via server
virtual TString GetDefaultPageContent()
Provides content of default web page for registered web-socket handler Can be content of HTML page or...
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
virtual ~THttpServer()
destructor delete all http engines and sniffer
Bool_t RegisterCommand(const char *cmdname, const char *method, const char *icon)
Register command which can be executed from web interface.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
char * Form(const char *fmt,...)
virtual Bool_t Create(const char *)
Method to create all components of engine.
Handles synchronous and a-synchronous timer events.
The ROOT global object gROOT contains a list of all defined classes.
RooCmdArg Restrict(const char *catName, const char *stateNameList)
void SetSniffer(TRootSniffer *sniff)
Set TRootSniffer to the server Server takes ownership over sniffer.
void ScanHierarchy(const char *topname, const char *path, TRootSnifferStore *store, Bool_t only_fields=kFALSE)
Method scans normal objects, registered in ROOT.
virtual TObjLink * FirstLink() const
TString & Remove(Ssiz_t pos)
std::condition_variable fCond
! condition used to wait for processing
void AddLocation(const char *prefix, const char *path)
add files location, which could be used in the server one could map some system folder to the server ...
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
std::mutex fMutex
! mutex to protect list with arguments
virtual void Terminate()
Method called when server want to be terminated.
void SetXml()
Set content type as "text/xml".
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
std::string fDefaultPage
! file name for default page name
void ParseOptions() const
Parse URL options into a key/value map.
Mother of all ROOT objects.
Long_t fMainThrdId
! id of the main ROOT process
void AddHeader(const char *name, const char *value)
Set name: value pair to reply header Content-Type field handled separately - one should use SetConten...
void SetReadOnly(Bool_t on=kTRUE)
When readonly on (default), sniffer is not allowed to change ROOT structures For instance, it is not allowed to read new objects from files.
const char * GetCors() const
Returns specified CORS domain.
virtual void Add(TObject *obj)
void SetOptions(const char *opt)
TList fCallArgs
! submitted arguments
void SetZipping(Int_t mode=kZipLarge)
static Bool_t VerifyFilePath(const char *fname)
Checked that filename does not contains relative path below current directory Used to prevent access ...
std::string fDefaultPageCont
! content of default html page
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Int_t GetIntValueFromOptions(const char *key) const
Return a value for a given key from the URL options as an Int_t, a missing key returns -1...
TString fJSROOT
! location of external JSROOT files
virtual const char * GetName() const
Returns name of object.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void SetCurrentCallArg(THttpCallArg *arg)
set current http arguments, which then used in different process methods For instance, if user authorized with some user name, depending from restrictions some objects will be invisible or user get full access to the element
static const struct @132 builtin_mime_types[]
void SetScanGlobalDir(Bool_t on=kTRUE)
When enabled (default), sniffer scans gROOT for files, canvases, histograms.
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
TRootSniffer * GetSniffer() const
returns pointer on objects sniffer
TString fFileName
! file name
const char * GetItemField(TFolder *parent, TObject *item, const char *name)
return field for specified item
Bool_t IsFileRequested(const char *uri, TString &res) const
Check if file is requested, thread safe.
virtual Option_t * GetAddOption() const
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
TObject * FindTObjectInHierarchy(const char *path)
Search element in hierarchy, derived from TObject.
virtual void RemoveFirst()
void SetJSROOT(const char *location)
Set location of JSROOT to use with the server One could specify address like: https://root.cern.ch/js/3.3/ http://web-docs.gsi.de/~linev/js/3.3/ This allows to get new JSROOT features with old server, reduce load on THttpServer instance, also startup time can be improved When empty string specified (default), local copy of JSROOT is used (distributed with ROOT)
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
const char * Data() const