otsdaq_utilities  v2_02_00
src/WebGUI/js/visualizers_lib/ViewerRoot_lib/JsRoot/docs/HttpServer.md
1 # HTTP server in ROOT
2 
3 The idea of THttpServer is to provide remote http access to running ROOT application and enable HTML/JavaScript user interface. Any registered object can be requested and displayed in the web browser. There are many benefits of such approach:
4 
5  * standard http interface to ROOT application
6  * no any temporary ROOT files to access data
7  * user interface running in all browsers
8 
9 ## Starting the HTTP server
10 
11 To start the http server, at any time, create an instance of the [THttpServer](https://root.cern.ch/root/html/THttpServer.html) class like:
12 
13  serv = new THttpServer("http:8080");
14 
15 This will start a [civetweb](https://github.com/bel2125/civetweb)-based http server on the port 8080. Then one should be able to open the address "http://localhost:8080" in any modern browser (Firefox, Chrome, Opera, Safari, IE11) and browse objects created in application. By default, the server can access files, canvases, and histograms via the gROOT pointer. All those objects can be displayed with JSROOT graphics.
16 
17 There is a [snapshot (frozen copy)](https://root.cern.ch/js/latest/httpserver.C/) of such server, running in [tutorials/http/httpserver.C](https://github.com/root-mirror/root/blob/master/tutorials/http/httpserver.C) macro from ROOT tutorial.
18 
19 <iframe width="800" height="500" src="https://root.cern.ch/js/latest/httpserver.C/?layout=simple&item=Canvases/c1">
20 </iframe>
21 
22 One could specify several options when creating http server. They could be add as additional URL parameters to the constructor arguments like:
23 
24  serv = new THttpServer("http:8080?loopback&thrds=2");
25 
26 Following parameters are supported:
27 
28  - thrds=N - number of threads used by the civetweb (default is 5)
29  - top=name - configure top name, visible in the web browser
30  - auth_file=filename - authentication file name, created with htdigets utility
31  - auth_domain=domain - authentication domain
32  - loopback - bind specified port to loopback 127.0.0.1 address
33  - debug - enable debug mode, server always returns html page with request info
34 
35 If necessary, one could bind http server to specific IP address like:
36 
37  new THttpServer("http:192.168.1.17:8080")
38 
39 
40 
41 ## Registering objects
42 
43 At any time, one could register other objects with the command:
44 
45  TGraph* gr = new TGraph(10);
46  gr->SetName("gr1");
47  serv->Register("graphs/subfolder", gr);
48 
49 One should specify sub-folder name, where objects will be registered.
50 If sub-folder name does not starts with slash `/`, than top-name folder `/Objects/` will be prepended.
51 At any time one could unregister objects:
52 
53  serv->Unregister(gr);
54 
55 THttpServer does not take ownership over registered objects - they should be deleted by user.
56 
57 If the objects content is changing in the application, one could enable monitoring flag in the browser - then objects view will be regularly updated.
58 
59 
60 ## Command interface
61 
62 THttpServer class provide simple interface to invoke command from web browser.
63 One just register command like:
64 
65  serv->RegisterCommand("/DoSomething","SomeFunction()");
66 
67 Element with name `DoSomething` will appear in the web browser and can be clicked.
68 It will result in `gROOT->ProcessLineSync("SomeFunction()")` call.
69 
70 One could configure argument(s) for the command.
71 For that one should use `%arg1`, `%arg2` and so on identifiers. Like:
72 
73  serv->RegisterCommand("/DoSomething","SomeFunction(%arg1%,%arg2%)");
74 
75 User will be requested to enter arguments values, when command element clicked in the browser.
76 Example of the command which executes arbitrary string in appliction via ProcessLine looks like:
77 
78  serv->RegisterCommand("/Process","%arg1%");
79 
80 When registering command, one could specify icon name which will be displayed with the command.
81 
82  serv->RegisterCommand("/DoSomething","SomeFunction()", "rootsys/icons/ed_execute.png");
83 
84 In example usage of images from `$ROOTSYS/icons` directory is shown. One could prepend `button;`
85 string to the icon name to let browser show command as extra button. In last case one could hide command element from elements list:
86 
87  serv->Hide("/DoSomething");
88 
89 One can find example of command interface usage in [tutorials/http/httpcontrol.C](https://github.com/root-mirror/root/blob/master/tutorials/http/httpcontrol.C) macro.
90 
91 
92 
93 ## Configuring user access
94 
95 By default, the http server is open for anonymous access. One could restrict the access to the server for authenticated users only. First of all, one should create a password file, using the **htdigest** utility.
96 
97  [shell] htdigest -c .htdigest domain_name user_name
98 
99 It is recommended not to use special symbols in domain or user names. Several users can be add to the ".htdigest" file. When starting the server, the following arguments should be specified:
100 
101  root [0] new THttpServer("http:8080?auth_file=.htdigest&auth_domain=domain_name");
102 
103 After that, the web browser will automatically request to input a name/password for the domain "domain_name"
104 
105 Based on authorized accounts, one could restrict or enable access to some elements in the server objects hierarchy, using THttpServer::Restrict() method.
106 
107 For instance, one could hide complete folder from 'guest' account:
108 
109  root [6] serv->Restrict("/Folder", "hidden=guest");
110 
111 Or one could hide from all but 'admin' account:
112 
113  root [7] serv->Restrict("/Folder", "visible=admin");
114 
115 Hidden folders or objects can not be accessed via http protocol.
116 
117 By default server runs in readonly mode and do not allow methods execution via 'exe.json' or 'exe.bin' requests. To allow such action, one could either grant generic access for all or one could allow to execute only special method:
118 
119  root [8] serv->Restrict("/Folder/histo1", "allow=all");
120  root [9] serv->Restrict("/Folder/histo1", "allow_method=GetTitle");
121 
122 One could provide several options for the same item, separating them with '&' sign:
123 
124  root [10] serv->Restrict("/Folder/histo1", "allow_method=GetTitle&hide=guest");
125 
126 Complete list of supported options could be found in [TRootSniffer:Restrict()](https://root.cern.ch/root/html/TRootSniffer.html#TRootSniffer:Restrict) method documentation.
127 
128 
129 ## Using FastCGI interface
130 
131 [FastCGI](http://en.wikipedia.org/wiki/FastCGI) is a protocol for interfacing interactive programs with a web server like Apache, lighttpd, Microsoft ISS and many others.
132 
133 When starting THttpServer, one could specify:
134 
135  serv = new THttpServer("fastcgi:9000");
136 
137 In fact, the FastCGI interface can run in parallel to http server. One can just call:
138 
139  serv = new THttpServer("http:8080");
140  serv->CreateEngine("fastcgi:9000");
141 
142 One could specify a debug parameter to be able to adjust the FastCGI configuration on the web server:
143 
144  serv->CreateEngine("fastcgi:9000?debug=1");
145 
146 All user access will be ruled by the main web server. Authorized account names could be used to configure access restriction in THttpServer.
147 
148 ### Configure fastcgi with Apcahe2
149 
150 First of all, one should compile and install [mod_fastcgi](http://www.fastcgi.com) module.
151 Then *mod_fastcgi* should be specified in httpd.conf to load it when Apache server is started.
152 Finally in host configuration file one should have following lines:
153 
154  <IfModule mod_fastcgi.c>
155  FastCgiExternalServer "/srv/www/htdocs/root.app" -host rootapp_host_name:9000
156  </IfModule>
157 
158 Here is supposed that directory "/srv/www/htdocs" is root directory for web server.
159 Than one should be able to open address:
160 
161  http://apache_host_name/root.app/
162 
163 There are many ways to configure user authentication in Apache. Example of digest for FastCGI server:
164 
165  <Location "/root.app/">
166  AuthType Digest
167  AuthName "root"
168  AuthDigestDomain "/root.app/" "root"
169  AuthDigestProvider file
170  AuthUserFile "/srv/auth/auth.txt"
171  Require valid-user
172  </Location>
173 
174 
175 
176 ### Configure fastcgi with lighttpd
177 
178 An example of configuration file for *lighttpd* server is:
179 
180  server.modules += ( "mod_fastcgi" )
181  fastcgi.server = (
182  "/root.app" =>
183  (( "host" => "192.168.1.11",
184  "port" => 9000,
185  "check-local" => "disable",
186  "docroot" => "/"
187  ))
188  )
189 
190 Be aware, that with *lighttpd* one should specify IP address of the host, where ROOT application is running. Address of the ROOT application will be following:
191 
192  http://lighttpd_host_name/root.app/
193 
194 Example of authorization configuration for FastCGI connection:
195 
196  auth.require = ( "/root.app" => (
197  "method" => "digest",
198  "realm" => "root",
199  "require" => "valid-user"
200  ) )
201 
202 
203 ## Integration with existing applications
204 
205 In many practical cases no change of existing code is required. Opened files (and all objects inside), existing canvas and histograms are automatically scanned by the server and will be available to the users. If necessary, any object can be registered directly to the server with a **`THttpServer::Register()`** call.
206 
207 Central point of integration - when and how THttpServer get access to data from a running application. By default it is done during the gSystem->ProcessEvents() call - THttpServer uses a synchronous timer which is activated every 100 ms. Such approach works perfectly when running macros in an interactive ROOT session.
208 
209 If an application runs in compiled code and does not contain gSystem->ProcessEvents() calls, two method are available.
210 
211 ### Asynchronous timer
212 
213 The first method is to configure an asynchronous timer for the server, like for example:
214 
215  serv->SetTimer(100, kFALSE);
216 
217 Then, the timer will be activated even without any gSystem->ProcessEvents() method call. The main advantage of such method is that the application code can be used without any modifications. But there is no control when access to the application data is performed. It could happen just in-between of **`TH1::Fill()`** calls and an histogram object may be incomplete. Therefore such method is not recommended.
218 
219 
220 ### Regular calls of THttpServer::ProcessRequests() method
221 
222 The second method is preferable - one just inserts in the application regular calls of the THttpServer::ProcessRequests() method, like:
223 
224  serv->ProcessRequests();
225 
226 In such case, one can fully disable the timer of the server:
227 
228  serv->SetTimer(0, kTRUE);
229 
230 
231 
232 ## Data access from command shell
233 
234 The big advantage of the http protocol is that it is not only supported in web browsers, but also in many other applications. One could use http requests to directly access ROOT objects and data members from any kind of scripts.
235 
236 If one starts a server and register an object like for example:
237 
238  root [1] serv = new THttpServer("http:8080");
239  root [2] TNamed* n1 = new TNamed("obj", "title");
240  root [3] serv->Register("subfolder", n1);
241 
242 One could request a JSON representation of such object with the command:
243 
244  [shell] wget http://localhost:8080/Objects/subfolder/obj/root.json
245 
246 Then, its representation will look like:
247 
248  {
249  "_typename" : "TNamed",
250  "fUniqueID" : 0,
251  "fBits" : 50331656,
252  "fName" : "obj",
253  "fTitle" : "title"
254  }
255 
256 The following requests can be performed:
257 
258  - `root.bin` - binary data produced by object streaming with TBufferFile
259  - `root.json` - ROOT JSON representation for object and objects members
260  - `root.xml` - ROOT XML representation
261  - `root.png` - PNG image (if object drawing implemented)
262  - `root.gif` - GIF image
263  - `root.jpeg` - JPEG image
264  - `exe.json` - method execution in the object
265  - `exe.bin` - method execution, return result in binary form
266  - `cmd.json` - command execution
267  - `item.json` - item (object) properties, specified on the server
268  - `multi.json` - perform several requests at once
269  - `multi.bin` - perform several requests at once, return result in binary form
270 
271 All data will be automatically zipped if '.gz' extension is appended. Like:
272 
273  [shell] wget http://localhost:8080/Objects/subfolder/obj/root.json.gz
274 
275 If the access to the server is restricted with htdigest, it is recommended to use the **curl** program since only curl correctly implements such authentication method. The command will look like:
276 
277  [shell] curl --user "accout:password" http://localhost:8080/Objects/subfolder/obj/root.json --digest -o root.json
278 
279 
280 ### Objects data access in JSON format
281 
282 Request `root.json` implemented with [TBufferJSON](https://root.cern.ch/root/html/TBufferJSON.html) class. TBufferJSON generates such object representation, which could be directly used in [JSROOT](https://root.cern.ch/js/) for drawing. `root.json` request returns either complete object or just object member like:
283 
284  [shell] wget http://localhost:8080/Objects/subfolder/obj/fTitle/root.json
285 
286 The result will be: "title".
287 
288 For the `root.json` request one could specify the 'compact' parameter, which allow to reduce the number of spaces and new lines without data lost. This parameter can have values from '0' (no compression) till '3' (no spaces and new lines at all).
289 
290 Usage of `root.json` request is about as efficient as binary `root.bin` request. Comparison of different request methods with TH1 object shown in the table:
291 
292 | Request | Size |
293 | :---------------------- | :--------- |
294 | root.bin | 1658 bytes |
295 | root.bin.gz | 782 bytes |
296 | root.json | 7555 bytes |
297 | root.json?compact=3 | 5381 bytes |
298 | root.json.gz?compact=3 | 1207 bytes |
299 
300 One should remember that JSON representation always includes names of the data fields which are not present in the binary representation. Even then the size difference is negligible.
301 
302 `root.json` used in JSROOT to request objects from THttpServer.
303 
304 
305 ### Generating images out of objects
306 
307 For the ROOT classes which are implementing Draw method (like [TH1](https://root.cern.ch/root/html/TH1.html) or [TGraph](https://root.cern.ch/root/html/TGraph.html))
308 one could produce images with requests: `root.png`, `root.gif`, `root.jpeg`. For example:
309 
310  wget "http://localhost:8080/Files/hsimple.root/hpx/root.png?w=500&h=500&opt=lego1" -O lego1.png
311 
312 For all such requests following parameters could be specified:
313 
314  - `h` - image height
315  - `w` - image width
316  - `opt` - draw options
317 
318 
319 ### Methods execution
320 
321 By default THttpServer starts in monitoring (read-only) mode and therefore forbid any methods execution. One could specify read-write mode when server is started:
322 
323  serv = new THttpServer("http:8080;rw");
324 
325 Or one could disable read-only mode with the call:
326 
327  serv->SetReadOnly(kFALSE);
328 
329 Or one could allow access to the folder, object or specific object methods with:
330 
331  serv->Restrict("/Histograms", "allow=admin"); // allow full access for user with 'admin' account
332  serv->Restrict("/Histograms/hist1", "allow=all"); // allow full access for all users
333  serv->Restrict("/Histograms/hist1", "allow_method=Rebin"); // allow only Rebin method
334 
335 'exe.json' accepts following parameters:
336 
337  - `method` - name of method to execute
338  - `prototype` - method prototype (see [TClass::GetMethodWithPrototype](https://root.cern.ch/root/html/TClass.html#TClass:GetMethodWithPrototype) for details)
339  - `compact` - compact parameter, used to compress return value
340  - `_ret_object_` - name of the object which should be returned as result of method execution (used together with remote TTree::Draw call)
341 
342 Example of retrieving object title:
343 
344  [shell] wget 'http://localhost:8080/Objects/subfolder/obj/exe.json?method=GetTitle' -O title.json
345 
346 Example of TTree::Draw method execution:
347 
348  [shell] wget 'http://localhost:8080/Files/job1.root/ntuple/exe.json?method=Draw&prototype="Option_t*"&opt="px:py>>h1"&_ret_object_=h1' -O exe.json
349 
350 One also used `exe.bin` method - in this case results of method execution will be returned in binary format. In case when method returns temporary object, which should be delete at the end of command execution, one should specify `_destroy_result_` parameter in the URL string:
351 
352  [shell] wget 'http://localhost:8080/Objects/subfolder/obj/exe.json?method=Clone&_destroy_result_' -O clone.json
353 
354 If method required object as argument, it could be posted in binary or XML format as POST request. If binary form is used, one should specify following parameters:
355 
356  [shell] wget 'http://localhost:8080/hist/exe.json?method=Add&h1=_post_object_&_post_class_=TH1I&c1=10' --post-file=h.bin -O res.json
357 
358 Here is important to specify post object class, which is not stored in the binary buffer. When used XML form (produced with [TBufferXML::ConvertToXML](https://root.cern.ch/root/html/TBufferXML.html#TBufferXML:ConvertToXML)) method, only string with XML code could be specified:
359 
360  [shell] wget 'http://localhost:8080/hist/exe.json?method=Add&h1=_post_object_xml_&c1=10' --post-file=h.xml -O res.json
361 
362 To get debug information about command execution, one could submit `exe.txt` request with same arguments.
363 
364 
365 ### Commands execution
366 
367 If command registered to the server:
368 
369  serv->RegisterCommand("/Folder/Start", "DoSomthing()");
370 
371 It can be invoked with `cmd.json` request like:
372 
373  [shell] wget http://localhost:8080/Folder/Start/cmd.json -O result.txt
374 
375 If command fails, `false` will be returned, otherwise result of gROOT->ProcessLineSync() execution.
376 
377 If command definition include arguments:
378 
379  serv->RegisterCommand("/ResetCounter", "DoReset(%arg1%,%arg2%)");
380 
381 One could specify them in the URL string:
382 
383  [shell] wget http://localhost:8080/ResetCounter/cmd.json?arg1=7&arg2=12 -O result.txt
384 
385 
386 
387 ### Performing multiple requests at once
388 
389 To minimize traffic between sever and client, one could submit several requests at once. This is especially useful when big number of small objects should be requestsed simultaneosely. For this purposes `multi.bin` or `multi.json` requests could be used.
390 Both require string as POST data which format as:
391 
392  subfolder/item1/root.json\n
393  subfolder/item2/root.json\n
394  subfolder/item1/exe.json?method=GetTitle\n
395 
396 If such requests saved in 'req.txt' file, one could submit it with command:
397 
398  [shell] wget http://localhost:8080/multi.json?number=3 --post-file=req.txt -O result.json
399 
400 For `multi.json` request one could use only requests, returning JSON format (like `root.json` or `exe.json`). Result will be JSON array.
401 For `multi.bin` any kind of requests can be used. It returns binary buffer with following content:
402 
403  [size1 (little endian), 4 bytes] + [request1 result, size1 bytes]
404  [size2 (little endian), 4 bytes] + [request2 result, size2 bytes]
405  [size3 (little endian), 4 bytes] + [request3 result, size3 bytes]
406 
407 While POST data in request used to transfer list of multiple reqeusts, it is not possible to submit
408 such kind of requests, which themselvs require data from POST block.