Logo ROOT   6.14/05
Reference Guide
TCivetweb.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 "TCivetweb.h"
13 
14 #include "../civetweb/civetweb.h"
15 
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "THttpServer.h"
20 #include "THttpWSEngine.h"
21 #include "TUrl.h"
22 
23 //////////////////////////////////////////////////////////////////////////
24 // //
25 // TCivetwebWSEngine //
26 // //
27 // Implementation of THttpWSEngine for Civetweb //
28 // //
29 //////////////////////////////////////////////////////////////////////////
30 
31 class TCivetwebWSEngine : public THttpWSEngine {
32 protected:
33  struct mg_connection *fWSconn;
34 
35 public:
36  TCivetwebWSEngine(struct mg_connection *conn) : THttpWSEngine(), fWSconn(conn) {}
37 
38  virtual UInt_t GetId() const { return TString::Hash((void *)&fWSconn, sizeof(void *)); }
39 
40  virtual void ClearHandle() { fWSconn = nullptr; }
41 
42  virtual void Send(const void *buf, int len)
43  {
44  if (fWSconn)
45  mg_websocket_write(fWSconn, MG_WEBSOCKET_OPCODE_BINARY, (const char *)buf, len);
46  }
47 
48  /////////////////////////////////////////////////////////
49  /// Special method to send binary data with text header
50  /// For normal websocket it is two separated operation, for other engines could be combined together,
51  /// but emulates as two messages on client side
52  virtual void SendHeader(const char *hdr, const void *buf, int len)
53  {
54  if (fWSconn) {
55  mg_websocket_write(fWSconn, MG_WEBSOCKET_OPCODE_TEXT, hdr, strlen(hdr));
56  mg_websocket_write(fWSconn, MG_WEBSOCKET_OPCODE_BINARY, (const char *)buf, len);
57  }
58  }
59 
60  virtual void SendCharStar(const char *str)
61  {
62  if (fWSconn)
63  mg_websocket_write(fWSconn, MG_WEBSOCKET_OPCODE_TEXT, str, strlen(str));
64  }
65 };
66 
67 //////////////////////////////////////////////////////////////////////////
68 
69 int websocket_connect_handler(const struct mg_connection *conn, void *)
70 {
71  const struct mg_request_info *request_info = mg_get_request_info(conn);
72  if (!request_info)
73  return 1;
74 
75  TCivetweb *engine = (TCivetweb *)request_info->user_data;
76  if (!engine || engine->IsTerminating())
77  return 1;
78  THttpServer *serv = engine->GetServer();
79  if (!serv)
80  return 1;
81 
82  auto arg = std::make_shared<THttpCallArg>();
83  arg->SetPathAndFileName(request_info->local_uri); // path and file name
84  arg->SetQuery(request_info->query_string); // query arguments
85  arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
86  arg->SetMethod("WS_CONNECT");
87 
88  Bool_t execres = serv->ExecuteHttp(arg);
89 
90  return execres && !arg->Is404() ? 0 : 1;
91 }
92 
93 //////////////////////////////////////////////////////////////////////////
94 
95 void websocket_ready_handler(struct mg_connection *conn, void *)
96 {
97  const struct mg_request_info *request_info = mg_get_request_info(conn);
98 
99  TCivetweb *engine = (TCivetweb *)request_info->user_data;
100  if (!engine || engine->IsTerminating())
101  return;
102  THttpServer *serv = engine->GetServer();
103  if (!serv)
104  return;
105 
106  auto arg = std::make_shared<THttpCallArg>();
107  arg->SetPathAndFileName(request_info->local_uri); // path and file name
108  arg->SetQuery(request_info->query_string); // query arguments
109  arg->SetMethod("WS_READY");
110 
111  // delegate ownership to the arg, id will be automatically set
112  arg->CreateWSEngine<TCivetwebWSEngine>(conn);
113 
114  serv->ExecuteHttp(arg);
115 }
116 
117 //////////////////////////////////////////////////////////////////////////
118 
119 int websocket_data_handler(struct mg_connection *conn, int, char *data, size_t len, void *)
120 {
121  const struct mg_request_info *request_info = mg_get_request_info(conn);
122 
123  // do not handle empty data
124  if (len == 0)
125  return 1;
126 
127  TCivetweb *engine = (TCivetweb *)request_info->user_data;
128  if (!engine || engine->IsTerminating())
129  return 1;
130  THttpServer *serv = engine->GetServer();
131  if (!serv)
132  return 1;
133 
134  // seems to be, appears when connection is broken
135  if ((len == 2) && ((int)data[0] == 3) && ((int)data[1] == -23))
136  return 0;
137 
138  auto arg = std::make_shared<THttpCallArg>();
139  arg->SetPathAndFileName(request_info->local_uri); // path and file name
140  arg->SetQuery(request_info->query_string); // query arguments
141  arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
142  arg->SetMethod("WS_DATA");
143 
144  arg->SetPostData(std::string(data,len));
145 
146  serv->ExecuteHttp(arg);
147 
148  return 1;
149 }
150 
151 //////////////////////////////////////////////////////////////////////////
152 
153 void websocket_close_handler(const struct mg_connection *conn, void *)
154 {
155  const struct mg_request_info *request_info = mg_get_request_info(conn);
156 
157  TCivetweb *engine = (TCivetweb *)request_info->user_data;
158  if (!engine || engine->IsTerminating())
159  return;
160  THttpServer *serv = engine->GetServer();
161  if (!serv)
162  return;
163 
164  auto arg = std::make_shared<THttpCallArg>();
165  arg->SetPathAndFileName(request_info->local_uri); // path and file name
166  arg->SetQuery(request_info->query_string); // query arguments
167  arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
168  arg->SetMethod("WS_CLOSE");
169 
170  serv->SubmitHttp(arg); // delegate ownership to server
171 }
172 
173 //////////////////////////////////////////////////////////////////////////
174 
175 static int log_message_handler(const struct mg_connection *conn, const char *message)
176 {
177  const struct mg_context *ctx = mg_get_context(conn);
178 
179  TCivetweb *engine = (TCivetweb *)mg_get_user_data(ctx);
180 
181  if (engine)
182  return engine->ProcessLog(message);
183 
184  // provide debug output
185  if ((gDebug > 0) || (strstr(message, "cannot bind to") != 0))
186  fprintf(stderr, "Error in <TCivetweb::Log> %s\n", message);
187 
188  return 0;
189 }
190 
191 //////////////////////////////////////////////////////////////////////////
192 
193 static int begin_request_handler(struct mg_connection *conn, void *)
194 {
195  const struct mg_request_info *request_info = mg_get_request_info(conn);
196 
197  TCivetweb *engine = (TCivetweb *)request_info->user_data;
198  if (!engine || engine->IsTerminating())
199  return 0;
200  THttpServer *serv = engine->GetServer();
201  if (!serv)
202  return 0;
203 
204  auto arg = std::make_shared<THttpCallArg>();
205 
206  TString filename;
207 
208  Bool_t execres = kTRUE, debug = engine->IsDebugMode();
209 
210  if (!debug && serv->IsFileRequested(request_info->local_uri, filename)) {
211  if ((filename.Index(".js") != kNPOS) || (filename.Index(".css") != kNPOS)) {
212  std::string buf = THttpServer::ReadFileContent(filename.Data());
213  if (buf.empty()) {
214  arg->Set404();
215  } else {
216  arg->SetContentType(THttpServer::GetMimeType(filename.Data()));
217  arg->SetContent(std::move(buf));
218  arg->AddHeader("Cache-Control", "max-age=3600");
219  arg->SetZipping();
220  }
221  } else {
222  arg->SetFile(filename.Data());
223  }
224  } else {
225  arg->SetPathAndFileName(request_info->local_uri); // path and file name
226  arg->SetQuery(request_info->query_string); // query arguments
227  arg->SetTopName(engine->GetTopName());
228  arg->SetMethod(request_info->request_method); // method like GET or POST
229  if (request_info->remote_user)
230  arg->SetUserName(request_info->remote_user);
231 
232  TString header;
233  for (int n = 0; n < request_info->num_headers; n++)
234  header.Append(
235  TString::Format("%s: %s\r\n", request_info->http_headers[n].name, request_info->http_headers[n].value));
236  arg->SetRequestHeader(header);
237 
238  const char *len = mg_get_header(conn, "Content-Length");
239  Int_t ilen = len ? TString(len).Atoi() : 0;
240 
241  if (ilen > 0) {
242  std::string buf;
243  buf.resize(ilen);
244  Int_t iread = mg_read(conn, (void *) buf.data(), ilen);
245  if (iread == ilen)
246  arg->SetPostData(std::move(buf));
247  }
248 
249  if (debug) {
250  TString cont;
251  cont.Append("<title>Civetweb echo</title>");
252  cont.Append("<h1>Civetweb echo</h1>\n");
253 
254  static int count = 0;
255 
256  cont.Append(TString::Format("Request %d:<br/>\n<pre>\n", ++count));
257  cont.Append(TString::Format(" Method : %s\n", arg->GetMethod()));
258  cont.Append(TString::Format(" PathName : %s\n", arg->GetPathName()));
259  cont.Append(TString::Format(" FileName : %s\n", arg->GetFileName()));
260  cont.Append(TString::Format(" Query : %s\n", arg->GetQuery()));
261  cont.Append(TString::Format(" PostData : %ld\n", arg->GetPostDataLength()));
262  if (arg->GetUserName())
263  cont.Append(TString::Format(" User : %s\n", arg->GetUserName()));
264 
265  cont.Append("</pre><p>\n");
266 
267  cont.Append("Environment:<br/>\n<pre>\n");
268  for (int n = 0; n < request_info->num_headers; n++)
269  cont.Append(
270  TString::Format(" %s = %s\n", request_info->http_headers[n].name, request_info->http_headers[n].value));
271  cont.Append("</pre><p>\n");
272 
273  arg->SetContentType("text/html");
274 
275  arg->SetContent(cont);
276 
277  } else {
278  execres = serv->ExecuteHttp(arg);
279  }
280  }
281 
282  if (!execres || arg->Is404()) {
283  std::string hdr = arg->FillHttpHeader("HTTP/1.1");
284  mg_printf(conn, "%s", hdr.c_str());
285  } else if (arg->IsFile()) {
286  mg_send_file(conn, (const char *)arg->GetContent());
287  } else {
288 
289  Bool_t dozip = kFALSE;
290  switch (arg->GetZipping()) {
291  case THttpCallArg::kNoZip: dozip = kFALSE; break;
293  if (arg->GetContentLength() < 10000) break;
294  case THttpCallArg::kZip:
295  // check if request header has Accept-Encoding
296  for (int n = 0; n < request_info->num_headers; n++) {
297  TString name = request_info->http_headers[n].name;
298  if (name.Index("Accept-Encoding", 0, TString::kIgnoreCase) != 0)
299  continue;
300  TString value = request_info->http_headers[n].value;
301  dozip = (value.Index("gzip", 0, TString::kIgnoreCase) != kNPOS);
302  break;
303  }
304 
305  break;
306  case THttpCallArg::kZipAlways: dozip = kTRUE; break;
307  }
308 
309  if (dozip)
310  arg->CompressWithGzip();
311 
312  std::string hdr = arg->FillHttpHeader("HTTP/1.1");
313  mg_printf(conn, "%s", hdr.c_str());
314 
315  if (arg->GetContentLength() > 0)
316  mg_write(conn, arg->GetContent(), (size_t)arg->GetContentLength());
317  }
318 
319  // Returning non-zero tells civetweb that our function has replied to
320  // the client, and civetweb should not send client any more data.
321  return 1;
322 }
323 
324 //////////////////////////////////////////////////////////////////////////
325 // //
326 // TCivetweb //
327 // //
328 // http server implementation, based on civetweb embedded server //
329 // It is default kind of engine, created for THttpServer //
330 // Currently v1.8 from https://github.com/civetweb/civetweb is used //
331 // //
332 // Following additional options can be specified: //
333 // top=foldername - name of top folder, seen in the browser //
334 // thrds=N - use N threads to run civetweb server (default 5) //
335 // auth_file - global authentication file //
336 // auth_domain - domain name, used for authentication //
337 // //
338 // Example: //
339 // new THttpServer("http:8080?top=MyApp&thrds=3"); //
340 // //
341 // Authentication: //
342 // When auth_file and auth_domain parameters are specified, access //
343 // to running http server will be possible only after user //
344 // authentication, using so-call digest method. To generate //
345 // authentication file, htdigest routine should be used: //
346 // //
347 // [shell] htdigest -c .htdigest domain_name user //
348 // //
349 // When creating server, parameters should be: //
350 // //
351 // new THttpServer("http:8080?auth_file=.htdigets&auth_domain=domain_name"); //
352 // //
353 //////////////////////////////////////////////////////////////////////////
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// constructor
357 
359  : THttpEngine("civetweb", "compact embedded http server"), fCtx(nullptr), fCallbacks(nullptr), fTopName(),
360  fDebug(kFALSE), fTerminating(kFALSE), fOnlySecured(only_secured)
361 {
362 }
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// destructor
366 
368 {
369  if (fCtx && !fTerminating)
370  mg_stop((struct mg_context *)fCtx);
371  if (fCallbacks)
372  free(fCallbacks);
373 }
374 
375 ////////////////////////////////////////////////////////////////////////////////
376 /// process civetweb log message, can be used to detect critical errors
377 
378 Int_t TCivetweb::ProcessLog(const char *message)
379 {
380  if ((gDebug > 0) || (strstr(message, "cannot bind to") != 0))
381  Error("Log", "%s", message);
382 
383  return 0;
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Creates embedded civetweb server
388 /// As main argument, http port should be specified like "8090".
389 /// Or one can provide combination of ipaddress and portnumber like 127.0.0.1:8090
390 /// Extra parameters like in URL string could be specified after '?' mark:
391 /// thrds=N - there N is number of threads used by the civetweb (default is 10)
392 /// top=name - configure top name, visible in the web browser
393 /// ssl_certificate=filename - SSL certificate, see docs/OpenSSL.md from civetweb
394 /// auth_file=filename - authentication file name, created with htdigets utility
395 /// auth_domain=domain - authentication domain
396 /// websocket_timeout=tm - set web sockets timeout in seconds (default 300)
397 /// websocket_disable - disable web sockets handling (default enabled)
398 /// bind - ip address to bind server socket
399 /// loopback - bind specified port to loopback 127.0.0.1 address
400 /// debug - enable debug mode, server always returns html page with request info
401 /// log=filename - configure civetweb log file
402 /// Examples:
403 /// http:8080?websocket_disable
404 /// http:7546?thrds=30&websocket_timeout=20
405 
406 Bool_t TCivetweb::Create(const char *args)
407 {
408  fCallbacks = malloc(sizeof(struct mg_callbacks));
409  memset(fCallbacks, 0, sizeof(struct mg_callbacks));
410  //((struct mg_callbacks *) fCallbacks)->begin_request = begin_request_handler;
411  ((struct mg_callbacks *)fCallbacks)->log_message = log_message_handler;
412  TString sport = IsSecured() ? "8480s" : "8080", num_threads = "10", websocket_timeout = "300000";
413  TString auth_file, auth_domain, log_file, ssl_cert;
414  Bool_t use_ws = kTRUE;
415 
416  // extract arguments
417  if (args && (strlen(args) > 0)) {
418 
419  // first extract port number
420  sport = "";
421  while ((*args != 0) && (*args != '?') && (*args != '/'))
422  sport.Append(*args++);
423  if (IsSecured() && (sport.Index("s")==kNPOS)) sport.Append("s");
424 
425  // than search for extra parameters
426  while ((*args != 0) && (*args != '?'))
427  args++;
428 
429  if (*args == '?') {
430  TUrl url(TString::Format("http://localhost/folder%s", args));
431 
432  if (url.IsValid()) {
433  url.ParseOptions();
434 
435  const char *top = url.GetValueFromOptions("top");
436  if (top)
437  fTopName = top;
438 
439  const char *log = url.GetValueFromOptions("log");
440  if (log)
441  log_file = log;
442 
443  Int_t thrds = url.GetIntValueFromOptions("thrds");
444  if (thrds > 0)
445  num_threads.Form("%d", thrds);
446 
447  const char *afile = url.GetValueFromOptions("auth_file");
448  if (afile)
449  auth_file = afile;
450 
451  const char *adomain = url.GetValueFromOptions("auth_domain");
452  if (adomain)
453  auth_domain = adomain;
454 
455  const char *sslc = url.GetValueFromOptions("ssl_cert");
456  if (sslc)
457  ssl_cert = sslc;
458 
459  Int_t wtmout = url.GetIntValueFromOptions("websocket_timeout");
460  if (wtmout > 0) {
461  websocket_timeout.Format("%d", wtmout * 1000);
462  use_ws = kTRUE;
463  }
464 
465  if (url.HasOption("websocket_disable"))
466  use_ws = kFALSE;
467 
468  if (url.HasOption("debug"))
469  fDebug = kTRUE;
470 
471  if (url.HasOption("loopback") && (sport.Index(":") == kNPOS))
472  sport = TString("127.0.0.1:") + sport;
473 
474  if (url.HasOption("bind") && (sport.Index(":") == kNPOS)) {
475  const char *addr = url.GetValueFromOptions("bind");
476  if (addr && strlen(addr))
477  sport = TString(addr) + ":" + sport;
478  }
479 
480  if (GetServer() && url.HasOption("cors")) {
481  const char *cors = url.GetValueFromOptions("cors");
482  GetServer()->SetCors(cors && *cors ? cors : "*");
483  }
484  }
485  }
486  }
487 
488  const char *options[20];
489  int op(0);
490 
491  Info("Create", "Starting HTTP server on port %s", sport.Data());
492 
493  options[op++] = "listening_ports";
494  options[op++] = sport.Data();
495  options[op++] = "num_threads";
496  options[op++] = num_threads.Data();
497 
498  if (use_ws) {
499  options[op++] = "websocket_timeout_ms";
500  options[op++] = websocket_timeout.Data();
501  }
502 
503  if ((auth_file.Length() > 0) && (auth_domain.Length() > 0)) {
504  options[op++] = "global_auth_file";
505  options[op++] = auth_file.Data();
506  options[op++] = "authentication_domain";
507  options[op++] = auth_domain.Data();
508  }
509 
510  if (log_file.Length() > 0) {
511  options[op++] = "error_log_file";
512  options[op++] = log_file.Data();
513  }
514 
515  if (ssl_cert.Length() > 0) {
516  options[op++] = "ssl_certificate";
517  options[op++] = ssl_cert.Data();
518  } else if (IsSecured())
519  Error("Create", "No SSL certificate file configured");
520 
521  options[op++] = nullptr;
522 
523  // Start the web server.
524  fCtx = mg_start((struct mg_callbacks *)fCallbacks, this, options);
525 
526  if (!fCtx)
527  return kFALSE;
528 
529  mg_set_request_handler((struct mg_context *)fCtx, "/", begin_request_handler, nullptr);
530 
531  if (use_ws)
532  mg_set_websocket_handler((struct mg_context *)fCtx, "**root.websocket$", websocket_connect_handler,
534 
535  return kTRUE;
536 }
const char * remote_user
Definition: civetweb.h:102
const char * local_uri
Definition: civetweb.h:93
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
TString fTopName
! name of top item
Definition: TCivetweb.h:22
void websocket_ready_handler(struct mg_connection *conn, void *)
Definition: TCivetweb.cxx:95
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
This class represents a WWW compatible URL.
Definition: TUrl.h:35
int mg_read(struct mg_connection *conn, void *buf, size_t len)
Definition: civetweb.c:6038
void mg_stop(struct mg_context *ctx)
Definition: civetweb.c:16590
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
Basic string class.
Definition: TString.h:131
virtual Bool_t Create(const char *args)
Creates embedded civetweb server As main argument, http port should be specified like "8090"...
Definition: TCivetweb.cxx:406
Bool_t IsSecured() const
Definition: TCivetweb.h:29
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual void Send(const void *buf, int len)=0
#define malloc
Definition: civetweb.c:1347
Bool_t IsValid() const
Definition: TUrl.h:82
Bool_t fDebug
! debug mode
Definition: TCivetweb.h:23
const char * GetTopName() const
Definition: TCivetweb.h:37
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:626
void * fCallbacks
! call-back table for civetweb webserver
Definition: TCivetweb.h:21
THttpServer * GetServer() const
Returns pointer to THttpServer associated with engine.
Definition: THttpEngine.h:40
virtual void SendCharStar(const char *str)
Envelope for sending string via the websocket.
void websocket_close_handler(const struct mg_connection *conn, void *)
Definition: TCivetweb.cxx:153
const char * request_method
Definition: civetweb.h:90
virtual void SendHeader(const char *hdr, const void *buf, int len)=0
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
virtual ~TCivetweb()
destructor
Definition: TCivetweb.cxx:367
void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
Definition: civetweb.c:12191
Int_t ProcessLog(const char *message)
process civetweb log message, can be used to detect critical errors
Definition: TCivetweb.cxx:378
int websocket_connect_handler(const struct mg_connection *conn, void *)
Definition: TCivetweb.cxx:69
TString & Append(const char *cs)
Definition: TString.h:559
void SetCors(const std::string &domain="*")
Enable CORS header to ProcessRequests() responses Specified location (typically "*") add as "Access-C...
Definition: THttpServer.h:91
void mg_send_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:9027
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
Definition: TUrl.cxx:649
int mg_printf(struct mg_connection *conn, const char *fmt,...)
Definition: civetweb.c:6346
Bool_t fTerminating
! server doing shutdown and not react on requests
Definition: TCivetweb.h:24
virtual UInt_t GetId() const =0
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
Ssiz_t Length() const
Definition: TString.h:405
TCivetweb(Bool_t only_secured=kFALSE)
constructor
Definition: TCivetweb.cxx:358
struct mg_header http_headers[MG_MAX_HEADERS]
Definition: civetweb.h:119
struct mg_context * mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **options)
Definition: civetweb.c:16676
int mg_write(struct mg_connection *conn, const void *buf, size_t len)
Definition: civetweb.c:6138
const Bool_t kFALSE
Definition: RtypesCore.h:88
const char * mg_get_header(const struct mg_connection *conn, const char *name)
Definition: civetweb.c:3628
static int log_message_handler(const struct mg_connection *conn, const char *message)
Definition: TCivetweb.cxx:175
CIVETWEB_API int mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
void * mg_get_user_data(const struct mg_context *ctx)
Definition: civetweb.c:3129
#define free
Definition: civetweb.c:1350
void ParseOptions() const
Parse URL options into a key/value map.
Definition: TUrl.cxx:618
void * user_data
Definition: civetweb.h:115
Bool_t IsDebugMode() const
Definition: TCivetweb.h:39
int websocket_data_handler(struct mg_connection *conn, int, char *data, size_t len, void *)
Definition: TCivetweb.cxx:119
const struct mg_request_info * mg_get_request_info(const struct mg_connection *conn)
Definition: civetweb.c:3368
const char * name
Definition: civetweb.h:83
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1896
virtual void ClearHandle()=0
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
const char * query_string
Definition: civetweb.h:100
static int begin_request_handler(struct mg_connection *conn, void *)
Definition: TCivetweb.cxx:193
void mg_set_websocket_handler(struct mg_context *ctx, const char *uri, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
Definition: civetweb.c:12212
const Bool_t kTRUE
Definition: RtypesCore.h:87
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
Definition: TUrl.cxx:672
const Int_t n
Definition: legend1.C:16
const char * value
Definition: civetweb.h:84
Bool_t IsFileRequested(const char *uri, TString &res) const
Check if file is requested, thread safe.
char name[80]
Definition: TGX11.cxx:109
double log(double)
struct mg_context * mg_get_context(const struct mg_connection *conn)
Definition: civetweb.c:3122
void * fCtx
! civetweb context
Definition: TCivetweb.h:20
const char * Data() const
Definition: TString.h:364
Bool_t IsTerminating() const
Definition: TCivetweb.h:41