24 #include "RConfigure.h"
47 class THttpTimer :
public TTimer {
64 if (fServer) fServer->ProcessRequests();
76 TLongPollEngine(
const char *
name,
const char *title) :
THttpWSEngine(name, title), fPoll(0), fBuf() {}
78 virtual ~TLongPollEngine() {}
82 const void *ptr = (
const void *)
this;
90 fPoll->NotifyCondition();
95 virtual void Send(
const void * ,
int )
97 Error(
"TLongPollEngine::Send",
"Should never be called, only text is supported");
103 fPoll->SetContentType(
"text/plain");
104 fPoll->SetContent(buf);
105 fPoll->NotifyCondition();
107 }
else if (fBuf.Length() == 0) {
110 Error(
"TLongPollEngine::SendCharStar",
"Too many send operations, use TList object instead");
123 Error(
"PreviewData",
"NEVER SHOULD HAPPEN");
128 Info(
"PreviewData",
"Get dummy request when previous not completed");
130 fPoll->SetContentType(
"text/plain");
131 fPoll->SetContent(
"<<nope>>");
132 fPoll->NotifyCondition();
136 if (fBuf.Length() > 0) {
209 :
TNamed("http", "ROOT http server"), fEngines(), fTimer(0), fSniffer(0), fMainThrdId(0), fJSROOTSYS(),
210 fTopName("ROOT"), fJSROOT(), fLocations(), fDefaultPage(), fDefaultPageCont(), fDrawPage(), fDrawPageCont(),
213 fLocations.SetOwner(
kTRUE);
215 #ifdef COMPILED_WITH_DABC
217 if (dabcsys != 0) fJSROOTSYS =
TString::Format(
"%s/plugins/root/js", dabcsys);
221 if (jsrootsys != 0) fJSROOTSYS = jsrootsys;
223 if (fJSROOTSYS.Length() == 0) {
226 Warning(
"THttpServer",
"problems resolving '%s', use JSROOTSYS to specify $ROOTSYS/etc/http location",
234 AddLocation(
"currentdir/",
".");
235 AddLocation(
"jsrootsys/", fJSROOTSYS);
238 fDefaultPage = fJSROOTSYS +
"/files/online.htm";
239 fDrawPage = fJSROOTSYS +
"/files/draw.htm";
246 if (strchr(engine,
';') == 0) {
247 CreateEngine(engine);
253 if ((strcmp(opt,
"readonly") == 0) || (strcmp(opt,
"ro") == 0)) {
254 GetSniffer()->SetReadOnly(
kTRUE);
255 }
else if ((strcmp(opt,
"readwrite") == 0) || (strcmp(opt,
"rw") == 0)) {
256 GetSniffer()->SetReadOnly(
kFALSE);
314 if ((prefix == 0) || (*prefix == 0))
return;
335 fJSROOT = location ? location :
"";
346 if ((filename != 0) && (*filename != 0))
363 if ((filename != 0) && (*filename != 0))
384 if (engine == 0)
return kFALSE;
386 const char *arg = strchr(engine,
':');
387 if (arg == 0)
return kFALSE;
390 if (arg != engine) clname.
Append(engine, arg - engine);
392 if ((clname.
Length() == 0) || (clname ==
"http") || (clname ==
"civetweb"))
393 clname =
"TCivetweb";
394 else if (clname ==
"fastcgi")
396 else if (clname ==
"dabc")
397 clname =
"TDabcEngine";
401 if (engine_class == 0)
return kFALSE;
404 if (eng == 0)
return kFALSE;
408 if (!eng->
Create(arg + 1)) {
435 fTimer =
new THttpTimer(milliSec, mode,
this);
446 if ((fname == 0) || (*fname == 0))
return kFALSE;
450 while (*fname != 0) {
453 const char *next = strpbrk(fname,
"/\\");
454 if (next == 0)
return kTRUE;
457 if ((next == fname + 2) && (*fname ==
'.') && (*(fname + 1) ==
'.')) {
460 if (level < 0)
return kFALSE;
465 if ((next == fname + 1) && (*fname ==
'.')) {
492 if ((uri == 0) || (strlen(uri) == 0))
return kFALSE;
498 while ((obj = iter()) != 0) {
500 if (pos ==
kNPOS)
continue;
504 if ((fname[0] ==
'/') && (res[res.
Length() - 1] ==
'/')) res.
Resize(res.
Length() - 1);
528 std::unique_lock<std::mutex> lk(
fMutex);
554 std::unique_lock<std::mutex> lk(
fMutex);
570 Error(
"ProcessRequests",
"Should be called only from main ROOT thread");
574 std::unique_lock<std::mutex> lk(
fMutex, std::defer_lock);
631 if (!repl.
EndsWith(
"/")) repl +=
"/";
635 const char *hjsontag =
"\"$$$h.json$$$\"";
648 "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
667 const char *rootjsontag =
"\"$$$root.json$$$\"";
668 const char *hjsontag =
"\"$$$h.json$$$\"";
675 if (!repl.
EndsWith(
"/")) repl +=
"/";
698 "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
726 if ((filename ==
"h.xml") || (filename ==
"get.xml")) {
730 arg->
fContent.
Form(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
746 }
else if (filename ==
"h.json") {
752 }
else if (filename ==
"root.websocket") {
760 }
else if (strcmp(arg->
GetMethod(),
"WS_CONNECT") == 0) {
765 }
else if (strcmp(arg->
GetMethod(),
"WS_READY") == 0) {
768 if (
gDebug > 0)
Info(
"ProcessRequest",
"Set WebSocket handle %p", wshandle);
773 }
else if (strcmp(arg->
GetMethod(),
"WS_DATA") == 0) {
779 }
else if (strcmp(arg->
GetMethod(),
"WS_CLOSE") == 0) {
785 if (
gDebug > 0)
Info(
"ProcessRequest",
"Clear WebSocket handle");
795 }
else if (filename ==
"root.longpoll") {
802 }
else if (arg->
fQuery ==
"connect") {
810 TLongPollEngine *handle =
new TLongPollEngine(
"longpoll", arg->
fPathName.
Data());
837 Int_t len = strlen(post);
838 void *buf =
malloc(len / 2 + 1);
839 char *sbuf = (
char *)buf;
845 if (
false ) arg->
Set404();
851 if (bindata != 0) arg->
SetBinData(bindata, bindatalen);
860 if (arg->
Is404())
return;
864 if (filename ==
"root.bin") {
873 "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
944 return SetItemField(foldername,
"_hidden", hide ?
"true" : (
const char *)0);
984 static const struct {
989 {
".json", 5,
"application/json"},
990 {
".bin", 4,
"application/x-binary"},
991 {
".gif", 4,
"image/gif"},
992 {
".jpg", 4,
"image/jpeg"},
993 {
".png", 4,
"image/png"},
994 {
".html", 5,
"text/html"},
995 {
".htm", 4,
"text/html"},
996 {
".shtm", 5,
"text/html"},
997 {
".shtml", 6,
"text/html"},
998 {
".css", 4,
"text/css"},
999 {
".js", 3,
"application/x-javascript"},
1000 {
".ico", 4,
"image/x-icon"},
1001 {
".jpeg", 5,
"image/jpeg"},
1002 {
".svg", 4,
"image/svg+xml"},
1003 {
".txt", 4,
"text/plain"},
1004 {
".torrent", 8,
"application/x-bittorrent"},
1005 {
".wav", 4,
"audio/x-wav"},
1006 {
".mp3", 4,
"audio/x-mp3"},
1007 {
".mid", 4,
"audio/mid"},
1008 {
".m3u", 4,
"audio/x-mpegurl"},
1009 {
".ogg", 4,
"application/ogg"},
1010 {
".ram", 4,
"audio/x-pn-realaudio"},
1011 {
".xslt", 5,
"application/xml"},
1012 {
".xsl", 4,
"application/xml"},
1013 {
".ra", 3,
"audio/x-pn-realaudio"},
1014 {
".doc", 4,
"application/msword"},
1015 {
".exe", 4,
"application/octet-stream"},
1016 {
".zip", 4,
"application/x-zip-compressed"},
1017 {
".xls", 4,
"application/excel"},
1018 {
".tgz", 4,
"application/x-tar-gz"},
1019 {
".tar", 4,
"application/x-tar"},
1020 {
".gz", 3,
"application/x-gunzip"},
1021 {
".arj", 4,
"application/x-arj-compressed"},
1022 {
".rar", 4,
"application/x-arj-compressed"},
1023 {
".rtf", 4,
"application/rtf"},
1024 {
".pdf", 4,
"application/pdf"},
1025 {
".swf", 4,
"application/x-shockwave-flash"},
1026 {
".mpg", 4,
"video/mpeg"},
1027 {
".webm", 5,
"video/webm"},
1028 {
".mpeg", 5,
"video/mpeg"},
1029 {
".mov", 4,
"video/quicktime"},
1030 {
".mp4", 4,
"video/mp4"},
1031 {
".m4v", 4,
"video/x-m4v"},
1032 {
".asf", 4,
"video/x-ms-asf"},
1033 {
".avi", 4,
"video/x-msvideo"},
1034 {
".bmp", 4,
"image/bmp"},
1035 {
".ttf", 4,
"application/x-font-ttf"},
1038 int path_len = strlen(path);
1048 return "text/plain";
1058 std::ifstream is(filename);
1061 is.seekg(0, is.end);
1063 is.seekg(0, is.beg);
1065 char *buf = (
char *)
malloc(len);
void SetZipping(Int_t kind)
Set kind of content zipping 0 - none 1 - only when supported in request header 2 - if supported and c...
Bool_t RegisterObject(const char *subfolder, TObject *obj)
Register object in subfolder structure subfolder parameter can have many levels like: ...
Bool_t IsContentType(const char *typ) const
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
virtual TObject * GetPrimitive(const char *name) const
Get primitive.
Bool_t Produce(const char *path, const char *file, const char *options, void *&ptr, Long_t &length, TString &str)
Method produce different kind of data out of object Parameter 'path' specifies object or object membe...
Bool_t IsStreamerInfoItem(const char *itemname)
Return true if it is streamer info item name.
virtual void Process()
Method regularly called in main ROOT context.
void SetWSHandle(TNamed *handle)
assign websocket handle with HTTP call
Int_t GetLast() const
Return index of last object in array.
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 Info(const char *method, const char *msgfmt,...) const
Issue info message.
const char * GetItemField(const char *fullname, const char *name)
virtual void ProcessData(THttpCallArg *arg)
process data received from the client
TString fQuery
! additional arguments
TString fTopName
! name of top folder, default - "ROOT"
static const TString & GetRootSys()
Get the rootsys directory in the installation. Static utility function.
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
void Restrict(const char *path, const char *options)
Restrict access to the specified location.
virtual void Send(const void *buf, int len)=0
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
void SetServer(THttpServer *serv)
virtual void AssignCanvas(TCanvas *canv)
assign canvas to the web socket connects with CanvasModified signal
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 SetPostponed()
mark reply as postponed - submitting thread will not be inform
void ProcessRequests()
Process submitted requests, must be called from main thread.
Bool_t CreateItem(const char *fullname, const char *title)
void SetContent(const char *c)
Set content directly.
const char * GetMethod() const
returns request method like GET or POST
virtual void SendCharStar(const char *str)
Envelope for sending string via the websocket.
const char * Data() const
TRootSniffer * fSniffer
! sniffer provides access to ROOT objects hierarchy
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
void SetPostData(void *data, Long_t length)
set data, posted with the request buffer should be allocated with malloc(length+1) call...
Bool_t SetItemField(const char *fullname, const char *name, const char *value)
set field for specified item
Bool_t IsReadOnly() const
Returns readonly mode.
The TNamed class is the base class for all named ROOT classes.
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
void Clear()
Clear string without changing its capacity.
THttpTimer * fTimer
! timer used to access main thread
virtual Bool_t PreviewData(THttpCallArg *)
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)
std::vector< std::vector< double > > Data
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...
static Long_t SelfId()
Static method returning the id for the current thread.
void SetTimer(Long_t milliSec=100, Bool_t mode=kTRUE)
create timer which will invoke ProcessRequests() function periodically Timer is required to perform a...
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
const char * GetQuery() const
returns request query (string after ? in request URL)
TList fLocations
! list of local directories, which could be accessed via server
TString fJSROOTSYS
! location of local JSROOT files
Storage of hierarchy scan in TRootSniffer in XML format.
Bool_t SubmitHttp(THttpCallArg *arg, Bool_t can_run_immediately=kFALSE)
Submit HTTP request.
Bool_t Register(const char *subfolder, TObject *obj)
Register object in subfolder.
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
static struct @164 builtin_mime_types[]
void SetBinData(void *data, Long_t length)
set binary data, which will be returned as reply body
void SetJson()
set content type as JSON
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
Bool_t CreateEngine(const char *engine)
factory method to create different http engines At the moment two engine kinds are supported: civetwe...
Bool_t fNotifyFlag
! indicate that notification called
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
R__EXTERN TSystem * gSystem
virtual UInt_t GetId() const =0
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.
char * Form(const char *fmt,...)
Bool_t IsFileRequested(const char *uri, TString &res) const
Check if file is requested, thread safe.
TString fDefaultPage
! file name for default page name
Bool_t IsReadOnly() const
returns read-only mode
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.
void Warning(const char *location, const char *msgfmt,...)
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.
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Bool_t ExecuteHttp(THttpCallArg *arg)
Execute HTTP request.
TString fDrawPage
! file name for drawing of single element
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 ...
TCanvasImp * GetCanvasImp() const
Get canvas implementation pointer if any.
virtual Int_t GetSize() const
Bool_t Hide(const char *fullname, Bool_t hide=kTRUE)
hides folder or element from web gui
std::mutex fMutex
! mutex to protect list with arguments
virtual const char * GetName() const
Returns name of object.
void SetWSId(UInt_t id)
set web-socket id
virtual void ProcessRequest(THttpCallArg *arg)
Function called for every processed request.
TString fDrawPageCont
! content of draw page
void SetMethod(const char *method)
set request method kind like GET or POST
void SetXml()
set content type as XML
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
static TString BaseConvert(const TString &s_in, Int_t base_in, Int_t base_out)
Converts string from base base_in to base base_out.
void NotifyCondition()
method used to notify condition which waiting when operation will complete Condition notified only if...
TString fDefaultPageCont
! content of the file content
TNamed * TakeWSHandle()
takeout websocket handle with HTTP call can be done only once
Bool_t RegisterCommand(const char *cmdname, const char *method, const char *icon=0)
Register command which can be executed from web interface.
UInt_t GetWSId() const
get web-socket id
Mother of all ROOT objects.
static const char * GetMimeType(const char *path)
Guess mime type base on file extension.
Bool_t Unregister(TObject *obj)
Unregister object.
TString fContent
! text content (if any)
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
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...
static char * ReadFileContent(const char *filename, Int_t &len)
Reads content of file from the disk.
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.
virtual void Add(TObject *obj)
void SetFile(const char *filename=0)
indicate that http request should response with file content
Bool_t SetIcon(const char *fullname, const char *iconname)
set name of icon, used in browser together with the item
void SetOptions(const char *opt)
void ParseOptions() const
Parse URL options into a key/value map.
TList fCallArgs
! submitted arguments
virtual void ClearHandle()=0
static Bool_t VerifyFilePath(const char *fname)
Checked that filename does not contains relative path below current directory Used to prevent access ...
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
TString fJSROOT
! location of external JSROOT files
TObject * At(Int_t idx) const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
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
virtual const char * GetTitle() const
Returns title of object.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
void SetDrawPage(const char *filename)
Set file name of HTML page, delivered by the server when objects drawing page is requested from the b...
TString fFileName
! file name
Bool_t SetItemField(const char *fullname, const char *name, const char *value)
const char * GetItemField(TFolder *parent, TObject *item, const char *name)
return field for specified item
void Restrict(const char *path, const char *options)
Restrict access to specified object.
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
ULong_t GetStreamerInfoHash()
Returns hash value for streamer infos At the moment - just number of items in streamer infos list...
void SetDefaultPage(const char *filename)
Set file name of HTML page, delivered by the server when http address is opened in the browser...
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)
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.