Logo ROOT   6.14/05
Reference Guide
THttpServer.cxx
Go to the documentation of this file.
1 // $Id$
2 // Author: Sergey Linev 21/12/2013
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "THttpServer.h"
13 
14 #include "TThread.h"
15 #include "TTimer.h"
16 #include "TSystem.h"
17 #include "TROOT.h"
18 #include "TUrl.h"
19 #include "TClass.h"
20 #include "RVersion.h"
21 #include "RConfigure.h"
22 #include "TRegexp.h"
23 
24 #include "THttpEngine.h"
25 #include "THttpWSEngine.h"
26 #include "THttpLongPollEngine.h"
27 #include "THttpWSHandler.h"
28 #include "TRootSniffer.h"
29 #include "TRootSnifferStore.h"
30 #include "TCivetweb.h"
31 #include "TFastCgi.h"
32 
33 #include <string>
34 #include <cstdlib>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <fstream>
38 
39 ////////////////////////////////////////////////////////////////////////////////
40 
41 //////////////////////////////////////////////////////////////////////////
42 // //
43 // THttpTimer //
44 // //
45 // Specialized timer for THttpServer //
46 // Provides regular calls of THttpServer::ProcessRequests() method //
47 // //
48 //////////////////////////////////////////////////////////////////////////
49 
50 class THttpTimer : public TTimer {
51 public:
52  THttpServer &fServer; ///!< server processing requests
53 
54  /// constructor
55  THttpTimer(Long_t milliSec, Bool_t mode, THttpServer &serv) : TTimer(milliSec, mode), fServer(serv) {}
56 
57  /// timeout handler
58  /// used to process http requests in main ROOT thread
59  virtual void Timeout() { fServer.ProcessRequests(); }
60 };
61 
62 //////////////////////////////////////////////////////////////////////////////////////////////////
63 
64 //////////////////////////////////////////////////////////////////////////
65 // //
66 // THttpServer //
67 // //
68 // Online http server for arbitrary ROOT application //
69 // //
70 // Idea of THttpServer - provide remote http access to running //
71 // ROOT application and enable HTML/JavaScript user interface. //
72 // Any registered object can be requested and displayed in the browser. //
73 // There are many benefits of such approach: //
74 // * standard http interface to ROOT application //
75 // * no any temporary ROOT files when access data //
76 // * user interface running in all browsers //
77 // //
78 // Starting HTTP server //
79 // //
80 // To start http server, at any time create instance //
81 // of the THttpServer class like: //
82 // serv = new THttpServer("http:8080"); //
83 // //
84 // This will starts civetweb-based http server with http port 8080. //
85 // Than one should be able to open address "http://localhost:8080" //
86 // in any modern browser (IE, Firefox, Chrome) and browse objects, //
87 // created in application. By default, server can access files, //
88 // canvases and histograms via gROOT pointer. All such objects //
89 // can be displayed with JSROOT graphics. //
90 // //
91 // At any time one could register other objects with the command: //
92 // //
93 // TGraph* gr = new TGraph(10); //
94 // gr->SetName("gr1"); //
95 // serv->Register("graphs/subfolder", gr); //
96 // //
97 // If objects content is changing in the application, one could //
98 // enable monitoring flag in the browser - than objects view //
99 // will be regularly updated. //
100 // //
101 // More information: https://root.cern/root/htmldoc/guides/HttpServer/HttpServer.html //
102 // //
103 //////////////////////////////////////////////////////////////////////////
104 
106 
107 ////////////////////////////////////////////////////////////////////////////////
108 /// constructor
109 ///
110 /// As argument, one specifies engine kind which should be
111 /// created like "http:8080". One could specify several engines
112 /// at once, separating them with semicolon (";"). Following engines are supported:
113 ///
114 /// http - TCivetweb, civetweb-based implementation of http protocol
115 /// fastcgi - TFastCgi, special protocol for communicating with web servers
116 ///
117 /// For each created engine one should provide socket port number like "http:8080" or "fastcgi:9000".
118 /// Additional engine-specific options can be supplied with URL syntax like "http:8080?thrds=10".
119 /// Full list of supported options should be checked in engines docu.
120 ///
121 /// One also can configure following options, separated by semicolon:
122 ///
123 /// readonly, ro - set read-only mode (default)
124 /// readwrite, rw - allows methods execution of registered objects
125 /// global - scans global ROOT lists for existing objects (default)
126 /// noglobal - disable scan of global lists
127 /// cors - enable CORS header with origin="*"
128 /// cors=domain - enable CORS header with origin="domain"
129 /// basic_sniffer - use basic sniffer without support of hist, gpad, graph classes
130 ///
131 /// For example, create http server, which allows cors headers and disable scan of global lists,
132 /// one should provide "http:8080;cors;noglobal" as parameter
133 ///
134 /// THttpServer uses JavaScript ROOT (https://root.cern/js) to implement web clients UI.
135 /// Normally JSROOT sources are used from $ROOTSYS/etc/http directory,
136 /// but one could set JSROOTSYS shell variable to specify alternative location
137 
138 THttpServer::THttpServer(const char *engine) : TNamed("http", "ROOT http server")
139 {
140  const char *jsrootsys = gSystem->Getenv("JSROOTSYS");
141  if (jsrootsys)
142  fJSROOTSYS = jsrootsys;
143 
144  if (fJSROOTSYS.Length() == 0) {
145  TString jsdir = TString::Format("%s/http", TROOT::GetEtcDir().Data());
146  if (gSystem->ExpandPathName(jsdir)) {
147  Warning("THttpServer", "problems resolving '%s', use JSROOTSYS to specify $ROOTSYS/etc/http location",
148  jsdir.Data());
149  fJSROOTSYS = ".";
150  } else {
151  fJSROOTSYS = jsdir;
152  }
153  }
154 
155  AddLocation("currentdir/", ".");
156  AddLocation("jsrootsys/", fJSROOTSYS);
157  AddLocation("rootsys/", TROOT::GetRootSys());
158 
159  fDefaultPage = fJSROOTSYS + "/files/online.htm";
160  fDrawPage = fJSROOTSYS + "/files/draw.htm";
161 
162  TRootSniffer *sniff = nullptr;
163  if (strstr(engine, "basic_sniffer")) {
164  sniff = new TRootSniffer("sniff");
165  } else {
166  sniff = (TRootSniffer *)gROOT->ProcessLineSync("new TRootSnifferFull(\"sniff\");");
167  }
168 
169  SetSniffer(sniff);
170 
171  // start timer
172  SetTimer(20, kTRUE);
173 
174  if (strchr(engine, ';') == 0) {
175  CreateEngine(engine);
176  } else {
177  TObjArray *lst = TString(engine).Tokenize(";");
178 
179  for (Int_t n = 0; n <= lst->GetLast(); n++) {
180  const char *opt = lst->At(n)->GetName();
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) {
190  SetCors(opt + 5);
191  } else if (strcmp(opt, "cors") == 0) {
192  SetCors("*");
193  } else
194  CreateEngine(opt);
195  }
196 
197  delete lst;
198  }
199 }
200 
201 ////////////////////////////////////////////////////////////////////////////////
202 /// destructor
203 /// delete all http engines and sniffer
204 
206 {
207  THttpCallArg *arg = nullptr;
208  Bool_t owner = kFALSE;
209  while (true) {
210  // delete outside the locked mutex area
211  if (owner && arg)
212  delete arg;
213 
214  std::unique_lock<std::mutex> lk(fMutex);
215 
216  if (fCallArgs.GetSize() == 0)
217  break;
218  arg = static_cast<THttpCallArg *>(fCallArgs.First());
219  const char *opt = fCallArgs.FirstLink()->GetAddOption();
220  owner = opt && !strcmp(opt, "owner");
222  }
223 
224  if (fTerminated) {
225  TIter iter(&fEngines);
226  THttpEngine *engine = nullptr;
227  while ((engine = (THttpEngine *)iter()) != nullptr)
228  engine->Terminate();
229  }
230 
231  fEngines.Delete();
232 
233  SetSniffer(nullptr);
234 
235  SetTimer(0);
236 }
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// Set TRootSniffer to the server
240 /// Server takes ownership over sniffer
241 
243 {
244  if (fSniffer)
245  delete fSniffer;
246  fSniffer = sniff;
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Set termination flag,
251 /// No any further requests will be processed, server only can be destroyed afterwards
252 
254 {
255  fTerminated = kTRUE;
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// returns read-only mode
260 
262 {
263  return fSniffer ? fSniffer->IsReadOnly() : kTRUE;
264 }
265 
266 ////////////////////////////////////////////////////////////////////////////////
267 /// Set read-only mode for the server (default on)
268 /// In read-only server is not allowed to change any ROOT object, registered to the server
269 /// Server also cannot execute objects method via exe.json request
270 
272 {
273  if (fSniffer)
274  fSniffer->SetReadOnly(readonly);
275 }
276 
277 ////////////////////////////////////////////////////////////////////////////////
278 /// add files location, which could be used in the server
279 /// one could map some system folder to the server like AddLocation("mydir/","/home/user/specials");
280 /// Than files from this directory could be addressed via server like
281 /// http://localhost:8080/mydir/myfile.root
282 
283 void THttpServer::AddLocation(const char *prefix, const char *path)
284 {
285  if (!prefix || (*prefix == 0))
286  return;
287 
288  if (!path)
289  fLocations.erase(fLocations.find(prefix));
290  else
291  fLocations[prefix] = path;
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// Set location of JSROOT to use with the server
296 /// One could specify address like:
297 /// https://root.cern.ch/js/3.3/
298 /// http://web-docs.gsi.de/~linev/js/3.3/
299 /// This allows to get new JSROOT features with old server,
300 /// reduce load on THttpServer instance, also startup time can be improved
301 /// When empty string specified (default), local copy of JSROOT is used (distributed with ROOT)
302 
303 void THttpServer::SetJSROOT(const char *location)
304 {
305  fJSROOT = location ? location : "";
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Set file name of HTML page, delivered by the server when
310 /// http address is opened in the browser.
311 /// By default, $ROOTSYS/etc/http/files/online.htm page is used
312 /// When empty filename is specified, default page will be used
313 
314 void THttpServer::SetDefaultPage(const std::string &filename)
315 {
316  if (!filename.empty())
317  fDefaultPage = filename;
318  else
319  fDefaultPage = fJSROOTSYS + "/files/online.htm";
320 
321  // force to read page content next time again
322  fDefaultPageCont.clear();
323 }
324 
325 ////////////////////////////////////////////////////////////////////////////////
326 /// Set file name of HTML page, delivered by the server when
327 /// objects drawing page is requested from the browser
328 /// By default, $ROOTSYS/etc/http/files/draw.htm page is used
329 /// When empty filename is specified, default page will be used
330 
331 void THttpServer::SetDrawPage(const std::string &filename)
332 {
333  if (!filename.empty())
334  fDrawPage = filename;
335  else
336  fDrawPage = fJSROOTSYS + "/files/draw.htm";
337 
338  // force to read page content next time again
339  fDrawPageCont.clear();
340 }
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// factory method to create different http engines
344 /// At the moment two engine kinds are supported:
345 /// civetweb (default) and fastcgi
346 /// Examples:
347 /// "http:8080" or "civetweb:8080" or ":8080" - creates civetweb web server with http port 8080
348 /// "fastcgi:9000" - creates fastcgi server with port 9000
349 /// One could apply additional parameters, using URL syntax:
350 /// "http:8080?thrds=10"
351 
353 {
354  if (!engine)
355  return kFALSE;
356 
357  const char *arg = strchr(engine, ':');
358  if (!arg)
359  return kFALSE;
360 
361  TString clname;
362  if (arg != engine)
363  clname.Append(engine, arg - engine);
364 
365  THttpEngine *eng = nullptr;
366 
367  if ((clname.Length() == 0) || (clname == "http") || (clname == "civetweb")) {
368  eng = new TCivetweb(kFALSE);
369  } else if (clname == "https") {
370  eng = new TCivetweb(kTRUE);
371  } else if (clname == "fastcgi") {
372  eng = new TFastCgi();
373  }
374 
375  if (!eng) {
376  // ensure that required engine class exists before we try to create it
377  TClass *engine_class = gROOT->LoadClass(clname.Data());
378  if (!engine_class)
379  return kFALSE;
380 
381  eng = (THttpEngine *)engine_class->New();
382  if (!eng)
383  return kFALSE;
384  }
385 
386  eng->SetServer(this);
387 
388  if (!eng->Create(arg + 1)) {
389  delete eng;
390  return kFALSE;
391  }
392 
393  fEngines.Add(eng);
394 
395  return kTRUE;
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 /// create timer which will invoke ProcessRequests() function periodically
400 /// Timer is required to perform all actions in main ROOT thread
401 /// Method arguments are the same as for TTimer constructor
402 /// By default, sync timer with 100 ms period is created
403 ///
404 /// It is recommended to always use sync timer mode and only change period to
405 /// adjust server reaction time. Use of async timer requires, that application regularly
406 /// calls gSystem->ProcessEvents(). It happens automatically in ROOT interactive shell.
407 /// If milliSec == 0, no timer will be created.
408 /// In this case application should regularly call ProcessRequests() method.
409 ///
410 /// Async timer allows to use THttpServer in applications, which does not have explicit
411 /// gSystem->ProcessEvents() calls. But be aware, that such timer can interrupt any system call
412 /// (lise malloc) and can lead to dead locks, especially in multi-threaded applications.
413 
414 void THttpServer::SetTimer(Long_t milliSec, Bool_t mode)
415 {
416  if (fTimer) {
417  fTimer->Stop();
418  delete fTimer;
419  fTimer = nullptr;
420  }
421  if (milliSec > 0) {
422  fTimer = new THttpTimer(milliSec, mode, *this);
423  fTimer->TurnOn();
424  }
425 }
426 
427 ////////////////////////////////////////////////////////////////////////////////
428 /// Checked that filename does not contains relative path below current directory
429 /// Used to prevent access to files below current directory
430 
432 {
433  if (!fname || (*fname == 0))
434  return kFALSE;
435 
436  Int_t level = 0;
437 
438  while (*fname != 0) {
439 
440  // find next slash or backslash
441  const char *next = strpbrk(fname, "/\\");
442  if (next == 0)
443  return kTRUE;
444 
445  // most important - change to parent dir
446  if ((next == fname + 2) && (*fname == '.') && (*(fname + 1) == '.')) {
447  fname += 3;
448  level--;
449  if (level < 0)
450  return kFALSE;
451  continue;
452  }
453 
454  // ignore current directory
455  if ((next == fname + 1) && (*fname == '.')) {
456  fname += 2;
457  continue;
458  }
459 
460  // ignore slash at the front
461  if (next == fname) {
462  fname++;
463  continue;
464  }
465 
466  fname = next + 1;
467  level++;
468  }
469 
470  return kTRUE;
471 }
472 
473 ////////////////////////////////////////////////////////////////////////////////
474 /// Verifies that request is just file name
475 /// File names typically contains prefix like "jsrootsys/"
476 /// If true, method returns real name of the file,
477 /// which should be delivered to the client
478 /// Method is thread safe and can be called from any thread
479 
480 Bool_t THttpServer::IsFileRequested(const char *uri, TString &res) const
481 {
482  if (!uri || (*uri == 0))
483  return kFALSE;
484 
485  TString fname(uri);
486 
487  for (auto iter = fLocations.begin(); iter != fLocations.end(); iter++) {
488  Ssiz_t pos = fname.Index(iter->first.c_str());
489  if (pos == kNPOS)
490  continue;
491  fname.Remove(0, pos + (iter->first.length() - 1));
492  if (!VerifyFilePath(fname.Data()))
493  return kFALSE;
494  res = iter->second.c_str();
495  if ((fname[0] == '/') && (res[res.Length() - 1] == '/'))
496  res.Resize(res.Length() - 1);
497  res.Append(fname);
498  return kTRUE;
499  }
500 
501  return kFALSE;
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Executes http request, specified in THttpCallArg structure
506 /// Method can be called from any thread
507 /// Actual execution will be done in main ROOT thread, where analysis code is running.
508 
509 Bool_t THttpServer::ExecuteHttp(std::shared_ptr<THttpCallArg> arg)
510 {
511  if (fTerminated)
512  return kFALSE;
513 
514  if ((fMainThrdId != 0) && (fMainThrdId == TThread::SelfId())) {
515  // should not happen, but one could process requests directly without any signaling
516 
517  ProcessRequest(arg);
518 
519  return kTRUE;
520  }
521 
522  // add call arg to the list
523  std::unique_lock<std::mutex> lk(fMutex);
524  fArgs.push(arg);
525  // and now wait until request is processed
526  arg->fCond.wait(lk);
527 
528  return kTRUE;
529 }
530 
531 ////////////////////////////////////////////////////////////////////////////////
532 /// \deprecated Signature with shared_ptr should be used
533 /// Executes http request, specified in THttpCallArg structure
534 /// Method can be called from any thread
535 /// Actual execution will be done in main ROOT thread, where analysis code is running.
536 
537 Bool_t THttpServer::ExecuteHttp(THttpCallArg *arg)
538 {
539  if (fTerminated)
540  return kFALSE;
541 
542  if ((fMainThrdId != 0) && (fMainThrdId == TThread::SelfId())) {
543  // should not happen, but one could process requests directly without any signaling
544 
545  ProcessRequest(arg);
546 
547  return kTRUE;
548  }
549 
550  // add call arg to the list
551  std::unique_lock<std::mutex> lk(fMutex);
552  fCallArgs.Add(arg);
553  // and now wait until request is processed
554  arg->fCond.wait(lk);
555 
556  return kTRUE;
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// \deprecated Signature with shared_ptr should be used
561 /// Submit http request, specified in THttpCallArg structure
562 /// Contrary to ExecuteHttp, it will not block calling thread.
563 /// User should reimplement THttpCallArg::HttpReplied() method
564 /// to react when HTTP request is executed.
565 /// Method can be called from any thread
566 /// Actual execution will be done in main ROOT thread, where analysis code is running.
567 /// When called from main thread and can_run_immediately==kTRUE, will be
568 /// executed immediately.
569 /// If ownership==kTRUE, THttpCallArg object will be destroyed by the THttpServer
570 /// Returns kTRUE when was executed.
571 
572 Bool_t THttpServer::SubmitHttp(THttpCallArg *arg, Bool_t can_run_immediately, Bool_t ownership)
573 {
574  if (fTerminated) {
575  if (ownership)
576  delete arg;
577  return kFALSE;
578  }
579 
580  if (can_run_immediately && (fMainThrdId != 0) && (fMainThrdId == TThread::SelfId())) {
581  ProcessRequest(arg);
582  arg->NotifyCondition();
583  if (ownership)
584  delete arg;
585  return kTRUE;
586  }
587 
588  // add call arg to the list
589  std::unique_lock<std::mutex> lk(fMutex);
590  if (ownership)
591  fArgs.push(std::shared_ptr<THttpCallArg>(arg));
592  else
593  fCallArgs.Add(arg);
594  return kFALSE;
595 }
596 
597 ////////////////////////////////////////////////////////////////////////////////
598 /// Submit http request, specified in THttpCallArg structure
599 /// Contrary to ExecuteHttp, it will not block calling thread.
600 /// User should reimplement THttpCallArg::HttpReplied() method
601 /// to react when HTTP request is executed.
602 /// Method can be called from any thread
603 /// Actual execution will be done in main ROOT thread, where analysis code is running.
604 /// When called from main thread and can_run_immediately==kTRUE, will be
605 /// executed immediately.
606 /// Returns kTRUE when was executed.
607 
608 Bool_t THttpServer::SubmitHttp(std::shared_ptr<THttpCallArg> arg, Bool_t can_run_immediately)
609 {
610  if (fTerminated)
611  return kFALSE;
612 
613  if (can_run_immediately && (fMainThrdId != 0) && (fMainThrdId == TThread::SelfId())) {
614  ProcessRequest(arg);
615  arg->NotifyCondition();
616  return kTRUE;
617  }
618 
619  // add call arg to the list
620  std::unique_lock<std::mutex> lk(fMutex);
621  fArgs.push(arg);
622  return kFALSE;
623 }
624 
625 ////////////////////////////////////////////////////////////////////////////////
626 /// Process requests, submitted for execution
627 /// Regularly invoked by THttpTimer, when somewhere in the code
628 /// gSystem->ProcessEvents() is called.
629 /// User can call serv->ProcessRequests() directly, but only from main analysis thread.
630 
631 void THttpServer::ProcessRequests()
632 {
633  if (fMainThrdId == 0)
635 
636  if (fMainThrdId != TThread::SelfId()) {
637  Error("ProcessRequests", "Should be called only from main ROOT thread");
638  return;
639  }
640 
641  std::unique_lock<std::mutex> lk(fMutex, std::defer_lock);
642 
643  // first process requests in the queue
644  while (true) {
645  std::shared_ptr<THttpCallArg> arg;
646 
647  lk.lock();
648  if (!fArgs.empty()) {
649  arg = fArgs.front();
650  fArgs.pop();
651  }
652  lk.unlock();
653 
654  if (!arg)
655  break;
656 
657  fSniffer->SetCurrentCallArg(arg.get());
658 
659  try {
660  ProcessRequest(arg);
661  fSniffer->SetCurrentCallArg(nullptr);
662  } catch (...) {
663  fSniffer->SetCurrentCallArg(nullptr);
664  }
665 
666  arg->NotifyCondition();
667  }
668 
669  // then process old-style queue, will be removed later
670  while (true) {
671  THttpCallArg *arg = nullptr;
672 
673  lk.lock();
674  if (fCallArgs.GetSize() > 0) {
675  arg = static_cast<THttpCallArg *>(fCallArgs.First());
677  }
678  lk.unlock();
679 
680  if (!arg)
681  break;
682 
684 
685  try {
686  ProcessRequest(arg);
687  fSniffer->SetCurrentCallArg(nullptr);
688  } catch (...) {
689  fSniffer->SetCurrentCallArg(nullptr);
690  }
691 
692  arg->NotifyCondition();
693  }
694 
695  // regularly call Process() method of engine to let perform actions in ROOT context
696  TIter iter(&fEngines);
697  THttpEngine *engine = nullptr;
698  while ((engine = (THttpEngine *)iter()) != nullptr) {
699  if (fTerminated)
700  engine->Terminate();
701  engine->Process();
702  }
703 }
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// Method called when THttpServer cannot process request
707 /// By default such requests replied with 404 code
708 /// One could overwrite with method in derived class to process all kinds of such non-standard requests
709 
711 {
712  arg->Set404();
713 }
714 
715 ////////////////////////////////////////////////////////////////////////////////
716 /// Process single http request
717 /// Depending from requested path and filename different actions will be performed.
718 /// In most cases information is provided by TRootSniffer class
719 
720 void THttpServer::ProcessRequest(std::shared_ptr<THttpCallArg> arg)
721 {
722  if (fTerminated) {
723  arg->Set404();
724  return;
725  }
726 
727  if ((arg->fFileName != "root.websocket") && (arg->fFileName != "root.longpoll"))
728  return ProcessRequest(arg.get());
729 
730  THttpWSHandler *handler = dynamic_cast<THttpWSHandler *>(fSniffer->FindTObjectInHierarchy(arg->fPathName.Data()));
731 
732  if (!handler) {
733  arg->Set404();
734  return;
735  }
736 
737  if (arg->fFileName == "root.websocket") {
738  // handling of web socket
739  if (!handler->HandleWS(arg))
740  arg->Set404();
741  } else if (arg->fFileName == "root.longpoll") {
742  // ROOT emulation of websocket with polling requests
743  if ((arg->fQuery == "connect") || (arg->fQuery == "connect_raw")) {
744  // try to emulate websocket connect
745  // if accepted, reply with connection id, which must be used in the following communications
746  arg->SetMethod("WS_CONNECT");
747 
748  bool israw = (arg->fQuery == "connect_raw");
749 
750  // automatically assign engine to arg
751  arg->CreateWSEngine<THttpLongPollEngine>(israw);
752 
753  if (handler->HandleWS(arg)) {
754  arg->SetMethod("WS_READY");
755 
756  if (handler->HandleWS(arg))
757  arg->SetTextContent(std::string(israw ? "txt:" : "") + std::to_string(arg->GetWSId()));
758  } else {
759  arg->TakeWSEngine(); // delete handle
760  }
761  if (!arg->IsText())
762  arg->Set404();
763  } else {
764  TUrl url;
765  url.SetOptions(arg->fQuery);
766  url.ParseOptions();
767  Int_t connid = url.GetIntValueFromOptions("connection");
768  arg->SetWSId((UInt_t)connid);
769  if (url.HasOption("close")) {
770  arg->SetMethod("WS_CLOSE");
771  arg->SetTextContent("OK");
772  } else {
773  arg->SetMethod("WS_DATA");
774  }
775 
776  if (!handler->HandleWS(arg))
777  arg->Set404();
778  }
779  }
780 }
781 
782 ////////////////////////////////////////////////////////////////////////////////
783 /// \deprecated One should use signature with std::shared_ptr
784 /// Process single http request
785 /// Depending from requested path and filename different actions will be performed.
786 /// In most cases information is provided by TRootSniffer class
787 
789 {
790  if (fTerminated) {
791  arg->Set404();
792  return;
793  }
794 
795  if (arg->fFileName.IsNull() || (arg->fFileName == "index.htm")) {
796 
797  THttpWSHandler *handler(nullptr);
798 
799  if (arg->fFileName.IsNull())
800  handler = dynamic_cast<THttpWSHandler *>(fSniffer->FindTObjectInHierarchy(arg->fPathName.Data()));
801 
802  if (handler) {
803 
804  arg->fContent = handler->GetDefaultPageContent().Data();
805 
806  if (arg->fContent.find("file:") == 0) {
807  TString fname = arg->fContent.c_str() + 5;
808  fname.ReplaceAll("$jsrootsys", fJSROOTSYS);
809 
810  arg->fContent = ReadFileContent(fname.Data());
811  }
812  }
813 
814  if (arg->fContent.empty()) {
815 
816  if (fDefaultPageCont.empty())
817  fDefaultPageCont = ReadFileContent(fDefaultPage);
818 
819  arg->fContent = fDefaultPageCont;
820  }
821 
822  if (arg->fContent.empty()) {
823  arg->Set404();
824  } else {
825  // replace all references on JSROOT
826  if (fJSROOT.Length() > 0) {
827  std::string repl("=\"");
828  repl.append(fJSROOT.Data());
829  if (repl.back() != '/')
830  repl.append("/");
831  arg->ReplaceAllinContent("=\"jsrootsys/", repl);
832  }
833 
834  const char *hjsontag = "\"$$$h.json$$$\"";
835 
836  // add h.json caching
837  if (arg->fContent.find(hjsontag) != std::string::npos) {
838  TString h_json;
839  TRootSnifferStoreJson store(h_json, kTRUE);
840  const char *topname = fTopName.Data();
841  if (arg->fTopName.Length() > 0)
842  topname = arg->fTopName.Data();
843  fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);
844 
845  arg->ReplaceAllinContent(hjsontag, h_json.Data());
846 
847  arg->AddHeader("Cache-Control",
848  "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
849  if (arg->fQuery.Index("nozip") == kNPOS)
850  arg->SetZipping();
851  }
852  arg->SetContentType("text/html");
853  }
854  return;
855  }
856 
857  if (arg->fFileName == "draw.htm") {
858  if (fDrawPageCont.empty())
859  fDrawPageCont = ReadFileContent(fDrawPage);
860 
861  if (fDrawPageCont.empty()) {
862  arg->Set404();
863  } else {
864  const char *rootjsontag = "\"$$$root.json$$$\"";
865  const char *hjsontag = "\"$$$h.json$$$\"";
866 
867  arg->fContent = fDrawPageCont;
868 
869  // replace all references on JSROOT
870  if (fJSROOT.Length() > 0) {
871  std::string repl("=\"");
872  repl.append(fJSROOT.Data());
873  if (repl.back() != '/')
874  repl.append("/");
875  arg->ReplaceAllinContent("=\"jsrootsys/", repl);
876  }
877 
878  if ((arg->fQuery.Index("no_h_json") == kNPOS) && (arg->fQuery.Index("webcanvas") == kNPOS) &&
879  (arg->fContent.find(hjsontag) != std::string::npos)) {
880  TString h_json;
881  TRootSnifferStoreJson store(h_json, kTRUE);
882  const char *topname = fTopName.Data();
883  if (arg->fTopName.Length() > 0)
884  topname = arg->fTopName.Data();
885  fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store, kTRUE);
886 
887  arg->ReplaceAllinContent(hjsontag, h_json.Data());
888  }
889 
890  if ((arg->fQuery.Index("no_root_json") == kNPOS) && (arg->fQuery.Index("webcanvas") == kNPOS) &&
891  (arg->fContent.find(rootjsontag) != std::string::npos)) {
892  std::string str;
893  if (fSniffer->Produce(arg->fPathName.Data(), "root.json", "compact=23", str))
894  arg->ReplaceAllinContent(rootjsontag, str);
895  }
896  arg->AddHeader("Cache-Control",
897  "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
898  if (arg->fQuery.Index("nozip") == kNPOS)
899  arg->SetZipping();
900  arg->SetContentType("text/html");
901  }
902  return;
903  }
904 
905  if ((arg->fFileName == "favicon.ico") && arg->fPathName.IsNull()) {
906  arg->SetFile(fJSROOTSYS + "/img/RootIcon.ico");
907  return;
908  }
909 
910  TString filename;
911  if (IsFileRequested(arg->fFileName.Data(), filename)) {
912  arg->SetFile(filename);
913  return;
914  }
915 
916  filename = arg->fFileName;
917  Bool_t iszip = kFALSE;
918  if (filename.EndsWith(".gz")) {
919  filename.Resize(filename.Length() - 3);
920  iszip = kTRUE;
921  }
922 
923  if ((filename == "h.xml") || (filename == "get.xml")) {
924 
925  Bool_t compact = arg->fQuery.Index("compact") != kNPOS;
926 
927  TString res;
928 
929  res.Form("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
930  if (!compact)
931  res.Append("\n");
932  res.Append("<root>");
933  if (!compact)
934  res.Append("\n");
935  {
936  TRootSnifferStoreXml store(res, compact);
937 
938  const char *topname = fTopName.Data();
939  if (arg->fTopName.Length() > 0)
940  topname = arg->fTopName.Data();
941  fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store, filename == "get.xml");
942  }
943 
944  res.Append("</root>");
945  if (!compact)
946  res.Append("\n");
947 
948  arg->SetContent(std::string(res.Data()));
949 
950  arg->SetXml();
951  } else if (filename == "h.json") {
952  TString res;
953  TRootSnifferStoreJson store(res, arg->fQuery.Index("compact") != kNPOS);
954  const char *topname = fTopName.Data();
955  if (arg->fTopName.Length() > 0)
956  topname = arg->fTopName.Data();
957  fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);
958  arg->SetContent(std::string(res.Data()));
959  arg->SetJson();
960  } else if (fSniffer->Produce(arg->fPathName.Data(), filename.Data(), arg->fQuery.Data(), arg->fContent)) {
961  // define content type base on extension
962  arg->SetContentType(GetMimeType(filename.Data()));
963  } else {
964  // miss request, user may process
965  MissedRequest(arg);
966  }
967 
968  if (arg->Is404())
969  return;
970 
971  if (iszip)
973 
974  if (filename == "root.bin") {
975  // only for binary data master version is important
976  // it allows to detect if streamer info was modified
977  const char *parname = fSniffer->IsStreamerInfoItem(arg->fPathName.Data()) ? "BVersion" : "MVersion";
978  arg->AddHeader(parname, Form("%u", (unsigned)fSniffer->GetStreamerInfoHash()));
979  }
980 
981  // try to avoid caching on the browser
982  arg->AddHeader("Cache-Control",
983  "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
984 
985  // potentially add cors header
986  if (IsCors())
987  arg->AddHeader("Access-Control-Allow-Origin", GetCors());
988 }
989 
990 ////////////////////////////////////////////////////////////////////////////////
991 /// Register object in folders hierarchy
992 ///
993 /// See TRootSniffer::RegisterObject() for more details
994 
995 Bool_t THttpServer::Register(const char *subfolder, TObject *obj)
996 {
997  return fSniffer->RegisterObject(subfolder, obj);
998 }
999 
1000 ////////////////////////////////////////////////////////////////////////////////
1001 /// Unregister object in folders hierarchy
1002 ///
1003 /// See TRootSniffer::UnregisterObject() for more details
1004 
1005 Bool_t THttpServer::Unregister(TObject *obj)
1006 {
1007  return fSniffer->UnregisterObject(obj);
1008 }
1009 
1010 ////////////////////////////////////////////////////////////////////////////////
1011 /// Restrict access to specified object
1012 ///
1013 /// See TRootSniffer::Restrict() for more details
1014 
1015 void THttpServer::Restrict(const char *path, const char *options)
1016 {
1017  fSniffer->Restrict(path, options);
1018 }
1019 
1020 ////////////////////////////////////////////////////////////////////////////////
1021 /// Register command which can be executed from web interface
1022 ///
1023 /// As method one typically specifies string, which is executed with
1024 /// gROOT->ProcessLine() method. For instance
1025 /// serv->RegisterCommand("Invoke","InvokeFunction()");
1026 ///
1027 /// Or one could specify any method of the object which is already registered
1028 /// to the server. For instance:
1029 /// serv->Register("/", hpx);
1030 /// serv->RegisterCommand("/ResetHPX", "/hpx/->Reset()");
1031 /// Here symbols '/->' separates item name from method to be executed
1032 ///
1033 /// One could specify additional arguments in the command with
1034 /// syntax like %arg1%, %arg2% and so on. For example:
1035 /// serv->RegisterCommand("/ResetHPX", "/hpx/->SetTitle(\"%arg1%\")");
1036 /// serv->RegisterCommand("/RebinHPXPY", "/hpxpy/->Rebin2D(%arg1%,%arg2%)");
1037 /// Such parameter(s) will be requested when command clicked in the browser.
1038 ///
1039 /// Once command is registered, one could specify icon which will appear in the browser:
1040 /// serv->SetIcon("/ResetHPX", "rootsys/icons/ed_execute.png");
1041 ///
1042 /// One also can set extra property '_fastcmd', that command appear as
1043 /// tool button on the top of the browser tree:
1044 /// serv->SetItemField("/ResetHPX", "_fastcmd", "true");
1045 /// Or it is equivalent to specifying extra argument when register command:
1046 /// serv->RegisterCommand("/ResetHPX", "/hpx/->Reset()", "button;rootsys/icons/ed_delete.png");
1047 
1048 Bool_t THttpServer::RegisterCommand(const char *cmdname, const char *method, const char *icon)
1049 {
1050  return fSniffer->RegisterCommand(cmdname, method, icon);
1051 }
1052 
1053 ////////////////////////////////////////////////////////////////////////////////
1054 /// hides folder or element from web gui
1055 
1056 Bool_t THttpServer::Hide(const char *foldername, Bool_t hide)
1057 {
1058  return SetItemField(foldername, "_hidden", hide ? "true" : (const char *)0);
1059 }
1060 
1061 ////////////////////////////////////////////////////////////////////////////////
1062 /// set name of icon, used in browser together with the item
1063 ///
1064 /// One could use images from $ROOTSYS directory like:
1065 /// serv->SetIcon("/ResetHPX","/rootsys/icons/ed_execute.png");
1066 
1067 Bool_t THttpServer::SetIcon(const char *fullname, const char *iconname)
1068 {
1069  return SetItemField(fullname, "_icon", iconname);
1070 }
1071 
1072 ////////////////////////////////////////////////////////////////////////////////
1073 
1074 Bool_t THttpServer::CreateItem(const char *fullname, const char *title)
1075 {
1076  return fSniffer->CreateItem(fullname, title);
1077 }
1078 
1079 ////////////////////////////////////////////////////////////////////////////////
1080 
1081 Bool_t THttpServer::SetItemField(const char *fullname, const char *name, const char *value)
1082 {
1083  return fSniffer->SetItemField(fullname, name, value);
1084 }
1085 
1086 ////////////////////////////////////////////////////////////////////////////////
1087 
1088 const char *THttpServer::GetItemField(const char *fullname, const char *name)
1089 {
1090  return fSniffer->GetItemField(fullname, name);
1091 }
1092 
1093 ////////////////////////////////////////////////////////////////////////////////
1094 /// Returns MIME type base on file extension
1095 
1096 const char *THttpServer::GetMimeType(const char *path)
1097 {
1098  static const struct {
1099  const char *extension;
1100  int ext_len;
1101  const char *mime_type;
1102  } builtin_mime_types[] = {{".xml", 4, "text/xml"},
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"},
1150  {NULL, 0, NULL}};
1151 
1152  int path_len = strlen(path);
1153 
1154  for (int i = 0; builtin_mime_types[i].extension != NULL; i++) {
1155  if (path_len <= builtin_mime_types[i].ext_len)
1156  continue;
1157  const char *ext = path + (path_len - builtin_mime_types[i].ext_len);
1158  if (strcmp(ext, builtin_mime_types[i].extension) == 0) {
1159  return builtin_mime_types[i].mime_type;
1160  }
1161  }
1162 
1163  return "text/plain";
1164 }
1165 
1166 ////////////////////////////////////////////////////////////////////////////////
1167 /// reads file content
1168 
1169 char *THttpServer::ReadFileContent(const char *filename, Int_t &len)
1170 {
1171  len = 0;
1172 
1173  std::ifstream is(filename);
1174  if (!is)
1175  return 0;
1176 
1177  is.seekg(0, is.end);
1178  len = is.tellg();
1179  is.seekg(0, is.beg);
1180 
1181  char *buf = (char *)malloc(len);
1182  is.read(buf, len);
1183  if (!is) {
1184  free(buf);
1185  len = 0;
1186  return 0;
1187  }
1188 
1189  return buf;
1190 }
1191 
1192 ////////////////////////////////////////////////////////////////////////////////
1193 /// reads file content, using std::string as container
1194 
1195 std::string THttpServer::ReadFileContent(const std::string &filename)
1196 {
1197  std::ifstream is(filename);
1198  std::string res;
1199  if (is) {
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());
1204  if (!is)
1205  res.clear();
1206  }
1207  return res;
1208 }
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 *)
Definition: TRootSniffer.h:231
An array of TObjects.
Definition: TObjArray.h:37
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
std::string fContent
Definition: THttpCallArg.h:66
std::string fDrawPageCont
! content of draw html page
Definition: THttpServer.h:51
virtual void Process()
Method regularly called in main ROOT context.
Definition: THttpEngine.h:33
void ReplaceAllinContent(const std::string &from, const std::string &to)
Replace all occurrences of.
Bool_t IsReadOnly() const
Returns readonly mode.
Definition: TRootSniffer.h:187
const char * mime_type
Definition: civetweb.c:7147
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.
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
This class represents a WWW compatible URL.
Definition: TUrl.h:35
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
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...
#define gROOT
Definition: TROOT.h:410
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
Bool_t IsCors() const
Returns kTRUE if CORS was configured.
Definition: THttpServer.h:94
TString fQuery
! additional arguments
Definition: THttpCallArg.h:46
Basic string class.
Definition: TString.h:131
TString fTopName
! name of top folder, default - "ROOT"
Definition: THttpServer.h:43
int Int_t
Definition: RtypesCore.h:41
void SetDefaultPage(const std::string &filename="")
Set file name of HTML page, delivered by the server when http address is opened in the browser...
bool Bool_t
Definition: RtypesCore.h:59
static const TString & GetRootSys()
Get the rootsys directory in the installation. Static utility function.
Definition: TROOT.cxx:2907
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
Definition: THttpServer.h:36
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
void SetServer(THttpServer *serv)
Definition: THttpEngine.h:27
Bool_t fTerminated
! termination flag, disables all requests processing
Definition: THttpServer.h:39
void SetFile(const char *filename=nullptr)
indicate that http request should response with file content
Definition: THttpCallArg.h:168
#define malloc
Definition: civetweb.c:1347
void SetContentType(const char *typ)
set content type like "text/xml" or "application/json"
Definition: THttpCallArg.h:159
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
Definition: THttpServer.h:38
THttpServer(const char *engine="civetweb:8080")
constructor
std::queue< std::shared_ptr< THttpCallArg > > fArgs
! submitted arguments
Definition: THttpServer.h:56
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2286
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.
Definition: TNamed.h:29
THttpTimer * fTimer
! timer used to access main thread
Definition: THttpServer.h:37
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1638
TString fPathName
! item path
Definition: THttpCallArg.h:43
void Set404()
mark reply as 404 error - page/request not exists or refused
Definition: THttpCallArg.h:162
TString & Append(const char *cs)
Definition: TString.h:559
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2152
static Long_t SelfId()
Static method returning the id for the current thread.
Definition: TThread.cxx:547
void SetCors(const std::string &domain="*")
Enable CORS header to ProcessRequests() responses Specified location (typically "*") add as "Access-C...
Definition: THttpServer.h:91
virtual ULong_t GetStreamerInfoHash()
Definition: TRootSniffer.h:233
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
Definition: THttpServer.h:42
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
Definition: THttpCallArg.h:41
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
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
Definition: THttpServer.h:50
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
size_t ext_len
Definition: civetweb.c:7146
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
std::map< std::string, std::string > fLocations
! list of local directories, which could be accessed via server
Definition: THttpServer.h:46
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.
Definition: TString.cxx:2264
unsigned int UInt_t
Definition: RtypesCore.h:42
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.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:405
virtual Bool_t Create(const char *)
Method to create all components of engine.
Definition: THttpEngine.h:37
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
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
Definition: TList.h:108
const Bool_t kFALSE
Definition: RtypesCore.h:88
const char * extension
Definition: civetweb.c:7145
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
std::condition_variable fCond
! condition used to wait for processing
Definition: THttpCallArg.h:50
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.
Definition: TString.cxx:2172
#define ClassImp(name)
Definition: Rtypes.h:359
std::mutex fMutex
! mutex to protect list with arguments
Definition: THttpServer.h:54
virtual void Terminate()
Method called when server want to be terminated.
Definition: THttpEngine.h:30
void SetXml()
Set content type as "text/xml".
#define free
Definition: civetweb.c:1350
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:2991
std::string fDefaultPage
! file name for default page name
Definition: THttpServer.h:48
void ParseOptions() const
Parse URL options into a key/value map.
Definition: TUrl.cxx:618
Bool_t IsNull() const
Definition: TString.h:402
Mother of all ROOT objects.
Definition: TObject.h:37
Long_t fMainThrdId
! id of the main ROOT process
Definition: THttpServer.h:40
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.
Definition: TRootSniffer.h:184
const char * GetCors() const
Returns specified CORS domain.
Definition: THttpServer.h:97
virtual void Add(TObject *obj)
Definition: TList.h:87
void SetOptions(const char *opt)
Definition: TUrl.h:90
virtual void Timeout()
Definition: TTimer.h:96
TList fCallArgs
! submitted arguments
Definition: THttpServer.h:55
void SetZipping(Int_t mode=kZipLarge)
Definition: THttpCallArg.h:205
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
Definition: THttpServer.h:49
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1254
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...
Definition: TUrl.cxx:661
TString fJSROOT
! location of external JSROOT files
Definition: THttpServer.h:44
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
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
const Bool_t kTRUE
Definition: RtypesCore.h:87
static const struct @132 builtin_mime_types[]
void SetScanGlobalDir(Bool_t on=kTRUE)
When enabled (default), sniffer scans gROOT for files, canvases, histograms.
Definition: TRootSniffer.h:196
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
Definition: TUrl.cxx:672
TRootSniffer * GetSniffer() const
returns pointer on objects sniffer
Definition: THttpServer.h:75
const Int_t n
Definition: legend1.C:16
TString fFileName
! file name
Definition: THttpCallArg.h:44
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.
char name[80]
Definition: TGX11.cxx:109
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1070
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.
Definition: TClass.cxx:4792
const char * Data() const
Definition: TString.h:364