Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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#ifdef _MSC_VER
20#include <windows.h>
21#include <tchar.h>
22#endif
23
24#include "THttpServer.h"
25#include "THttpWSEngine.h"
26#include "TUrl.h"
27
28
29
30//////////////////////////////////////////////////////////////////////////
31// //
32// TCivetwebWSEngine //
33// //
34// Implementation of THttpWSEngine for Civetweb //
35// //
36//////////////////////////////////////////////////////////////////////////
37
39protected:
41
42 /// True websocket requires extra thread to parallelize sending
43 Bool_t SupportSendThrd() const override { return kTRUE; }
44
45public:
47
48 virtual ~TCivetwebWSEngine() = default;
49
50 UInt_t GetId() const override { return TString::Hash((void *)&fWSconn, sizeof(void *)); }
51
52 void ClearHandle(Bool_t terminate) override
53 {
54 if (fWSconn && terminate)
56 fWSconn = nullptr;
57 }
58
59 void Send(const void *buf, int len) override
60 {
61 if (fWSconn)
63 }
64
65 /////////////////////////////////////////////////////////
66 /// Special method to send binary data with text header
67 /// For normal websocket it is two separated operation, for other engines could be combined together,
68 /// but emulates as two messages on client side
69 void SendHeader(const char *hdr, const void *buf, int len) override
70 {
71 if (fWSconn) {
74 }
75 }
76
77 void SendCharStar(const char *str) override
78 {
79 if (fWSconn)
81 }
82};
83
84//////////////////////////////////////////////////////////////////////////
85
86int websocket_connect_handler(const struct mg_connection *conn, void *)
87{
88 const struct mg_request_info *request_info = mg_get_request_info(conn);
89 if (!request_info)
90 return 1;
91
92 TCivetweb *engine = (TCivetweb *)request_info->user_data;
93 if (!engine || engine->IsTerminating())
94 return 1;
95 THttpServer *serv = engine->GetServer();
96 if (!serv)
97 return 1;
98
99 auto arg = std::make_shared<THttpCallArg>();
100 arg->SetPathAndFileName(request_info->local_uri); // path and file name
101 arg->SetQuery(request_info->query_string); // query arguments
102 arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
103 arg->SetMethod("WS_CONNECT");
104
105 Bool_t execres = serv->ExecuteWS(arg, kTRUE, kTRUE);
106
107 return execres && !arg->Is404() ? 0 : 1;
108}
109
110//////////////////////////////////////////////////////////////////////////
111
112void websocket_ready_handler(struct mg_connection *conn, void *)
113{
114 const struct mg_request_info *request_info = mg_get_request_info(conn);
115
116 TCivetweb *engine = (TCivetweb *)request_info->user_data;
117 if (!engine || engine->IsTerminating())
118 return;
119 THttpServer *serv = engine->GetServer();
120 if (!serv)
121 return;
122
123 auto arg = std::make_shared<THttpCallArg>();
124 arg->SetPathAndFileName(request_info->local_uri); // path and file name
125 arg->SetQuery(request_info->query_string); // query arguments
126 arg->SetMethod("WS_READY");
127
128 // delegate ownership to the arg, id will be automatically set
129 arg->CreateWSEngine<TCivetwebWSEngine>(conn);
130
131 serv->ExecuteWS(arg, kTRUE, kTRUE);
132}
133
134
135//////////////////////////////////////////////////////////////////////////
136
137void websocket_close_handler(const struct mg_connection *conn, void *)
138{
139 const struct mg_request_info *request_info = mg_get_request_info(conn);
140
141 // check if connection was already closed
142 if (mg_get_user_connection_data(conn) == (void *) conn)
143 return;
144
145 TCivetweb *engine = (TCivetweb *)request_info->user_data;
146 if (!engine || engine->IsTerminating())
147 return;
148 THttpServer *serv = engine->GetServer();
149 if (!serv)
150 return;
151
152 auto arg = std::make_shared<THttpCallArg>();
153 arg->SetPathAndFileName(request_info->local_uri); // path and file name
154 arg->SetQuery(request_info->query_string); // query arguments
155 arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
156 arg->SetMethod("WS_CLOSE");
157
158 serv->ExecuteWS(arg, kTRUE, kFALSE); // do not wait for result of execution
159}
160
161//////////////////////////////////////////////////////////////////////////
162
163int websocket_data_handler(struct mg_connection *conn, int code, char *data, size_t len, void *)
164{
165 const struct mg_request_info *request_info = mg_get_request_info(conn);
166
167 // check if connection data set to connection itself - means connection was closed already
168 std::string *conn_data = (std::string *) mg_get_user_connection_data(conn);
169 if ((void *) conn_data == (void *) conn)
170 return 1;
171
172 // see https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
173 int fin = code & 0x80, opcode = code & 0x0F;
174
175 // recognized operation codes, all other should fails
176 enum { OP_CONTINUE = 0, OP_TEXT = 1, OP_BINARY = 2, OP_CLOSE = 8 };
177
178 // close when normal close is detected
179 if (fin && (opcode == OP_CLOSE)) {
180 if (conn_data) delete conn_data;
181 websocket_close_handler(conn, nullptr);
182 mg_set_user_connection_data(conn, conn); // mark connection as closed
183 return 1;
184 }
185
186 // ignore empty data
187 if (len == 0)
188 return 1;
189
190 // close connection when unrecognized opcode is detected
191 if ((opcode != OP_CONTINUE) && (opcode != OP_TEXT) && (opcode != OP_BINARY)) {
192 if (conn_data) delete conn_data;
193 websocket_close_handler(conn, nullptr);
194 mg_set_user_connection_data(conn, conn); // mark connection as closed
195 return 1;
196 }
197
198 TCivetweb *engine = (TCivetweb *)request_info->user_data;
199 if (!engine || engine->IsTerminating())
200 return 1;
201 THttpServer *serv = engine->GetServer();
202 if (!serv)
203 return 1;
204
205 // this is continuation of the request
206 if (!fin) {
207 if (!conn_data) {
208 conn_data = new std::string(data,len);
210 } else {
211 conn_data->append(data,len);
212 }
213 return 1;
214 }
215
216 auto arg = std::make_shared<THttpCallArg>();
217 arg->SetPathAndFileName(request_info->local_uri); // path and file name
218 arg->SetQuery(request_info->query_string); // query arguments
219 arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
220 arg->SetMethod("WS_DATA");
221
222 if (conn_data) {
223 mg_set_user_connection_data(conn, nullptr);
224 conn_data->append(data,len);
225 arg->SetPostData(std::move(*conn_data));
226 delete conn_data;
227 } else {
228 arg->SetPostData(std::string(data,len));
229 }
230
231 serv->ExecuteWS(arg, kTRUE, kTRUE);
232
233 return 1;
234}
235
236
237//////////////////////////////////////////////////////////////////////////
238
239static int log_message_handler(const struct mg_connection *conn, const char *message)
240{
241 const struct mg_context *ctx = mg_get_context(conn);
242
243 TCivetweb *engine = (TCivetweb *)mg_get_user_data(ctx);
244
245 if (engine)
246 return engine->ProcessLog(message);
247
248 // provide debug output
249 if ((gDebug > 0) || (strstr(message, "cannot bind to") != 0))
250 fprintf(stderr, "Error in <TCivetweb::Log> %s\n", message);
251
252 return 0;
253}
254
255//////////////////////////////////////////////////////////////////////////
256
257static int begin_request_handler(struct mg_connection *conn, void *)
258{
259 const struct mg_request_info *request_info = mg_get_request_info(conn);
260
261 TCivetweb *engine = (TCivetweb *)request_info->user_data;
262 if (!engine || engine->IsTerminating())
263 return 0;
264 THttpServer *serv = engine->GetServer();
265 if (!serv)
266 return 0;
267
268 auto arg = std::make_shared<THttpCallArg>();
269
270 TString filename;
271
272 Bool_t execres = kTRUE, debug = engine->IsDebugMode();
273
274 if (!debug && serv->IsFileRequested(request_info->local_uri, filename)) {
275 if ((filename.Length() > 3) && ((filename.Index(".js") != kNPOS) || (filename.Index(".css") != kNPOS))) {
276 std::string buf = THttpServer::ReadFileContent(filename.Data());
277 if (buf.empty()) {
278 arg->Set404();
279 } else {
280 arg->SetContentType(THttpServer::GetMimeType(filename.Data()));
281 arg->SetContent(std::move(buf));
282 if (engine->GetMaxAge() > 0)
283 arg->AddHeader("Cache-Control", TString::Format("max-age=%d", engine->GetMaxAge()));
284 else
285 arg->AddNoCacheHeader();
286 arg->SetZipping();
287 }
288 } else {
289 arg->SetFile(filename.Data());
290 }
291 } else {
292 arg->SetPathAndFileName(request_info->local_uri); // path and file name
293 arg->SetQuery(request_info->query_string); // query arguments
294 arg->SetTopName(engine->GetTopName());
295 arg->SetMethod(request_info->request_method); // method like GET or POST
296 if (request_info->remote_user)
297 arg->SetUserName(request_info->remote_user);
298
299 TString header;
300 for (int n = 0; n < request_info->num_headers; n++)
301 header.Append(
302 TString::Format("%s: %s\r\n", request_info->http_headers[n].name, request_info->http_headers[n].value));
303 arg->SetRequestHeader(header);
304
305 const char *len = mg_get_header(conn, "Content-Length");
306 Int_t ilen = len ? TString(len).Atoi() : 0;
307
308 if (ilen > 0) {
309 std::string buf;
310 buf.resize(ilen);
311 Int_t iread = mg_read(conn, (void *) buf.data(), ilen);
312 if (iread == ilen)
313 arg->SetPostData(std::move(buf));
314 }
315
316 if (debug) {
317 TString cont;
318 cont.Append("<title>Civetweb echo</title>");
319 cont.Append("<h1>Civetweb echo</h1>\n");
320
321 static int count = 0;
322
323 cont.Append(TString::Format("Request %d:<br/>\n<pre>\n", ++count));
324 cont.Append(TString::Format(" Method : %s\n", arg->GetMethod()));
325 cont.Append(TString::Format(" PathName : %s\n", arg->GetPathName()));
326 cont.Append(TString::Format(" FileName : %s\n", arg->GetFileName()));
327 cont.Append(TString::Format(" Query : %s\n", arg->GetQuery()));
328 cont.Append(TString::Format(" PostData : %ld\n", arg->GetPostDataLength()));
329 if (arg->GetUserName())
330 cont.Append(TString::Format(" User : %s\n", arg->GetUserName()));
331
332 cont.Append("</pre><p>\n");
333
334 cont.Append("Environment:<br/>\n<pre>\n");
335 for (int n = 0; n < request_info->num_headers; n++)
336 cont.Append(
337 TString::Format(" %s = %s\n", request_info->http_headers[n].name, request_info->http_headers[n].value));
338 cont.Append("</pre><p>\n");
339
340 arg->SetContentType("text/html");
341
342 arg->SetContent(cont);
343
344 } else {
345 execres = serv->ExecuteHttp(arg);
346 }
347 }
348
349 if (!execres || arg->Is404()) {
350 std::string hdr = arg->FillHttpHeader("HTTP/1.1");
351 mg_printf(conn, "%s", hdr.c_str());
352 } else if (arg->IsFile()) {
353 filename = (const char *)arg->GetContent();
354#ifdef _MSC_VER
355 // resolve Windows links which are not supported by civetweb
356 const int BUFSIZE = 2048;
357 TCHAR Path[BUFSIZE];
358
359 auto hFile = CreateFile(filename.Data(), // file to open
360 GENERIC_READ, // open for reading
361 FILE_SHARE_READ, // share for reading
362 NULL, // default security
363 OPEN_EXISTING, // existing file only
364 FILE_ATTRIBUTE_NORMAL, // normal file
365 NULL); // no attr. template
366
367 if( hFile != INVALID_HANDLE_VALUE) {
368 auto dwRet = GetFinalPathNameByHandle( hFile, Path, BUFSIZE, VOLUME_NAME_DOS );
369 // produced file name may include \\? symbols, which are indicating long file name
370 if(dwRet < BUFSIZE)
371 filename = Path;
372 CloseHandle(hFile);
373 }
374#endif
375 const char *mime_type = THttpServer::GetMimeType(filename.Data());
376 if (mime_type)
377 mg_send_mime_file(conn, filename.Data(), mime_type);
378 else
379 mg_send_file(conn, filename.Data());
380 } else {
381
382 Bool_t dozip = kFALSE;
383 switch (arg->GetZipping()) {
384 case THttpCallArg::kNoZip: dozip = kFALSE; break;
386 if (arg->GetContentLength() < 10000) break;
388 // check if request header has Accept-Encoding
389 for (int n = 0; n < request_info->num_headers; n++) {
390 TString name = request_info->http_headers[n].name;
391 if (name.Index("Accept-Encoding", 0, TString::kIgnoreCase) != 0)
392 continue;
393 TString value = request_info->http_headers[n].value;
394 dozip = (value.Index("gzip", 0, TString::kIgnoreCase) != kNPOS);
395 break;
396 }
397
398 break;
399 case THttpCallArg::kZipAlways: dozip = kTRUE; break;
400 }
401
402 if (dozip)
403 arg->CompressWithGzip();
404
405 std::string hdr = arg->FillHttpHeader("HTTP/1.1");
406 mg_printf(conn, "%s", hdr.c_str());
407
408 if (arg->GetContentLength() > 0)
409 mg_write(conn, arg->GetContent(), (size_t)arg->GetContentLength());
410 }
411
412 // Returning non-zero tells civetweb that our function has replied to
413 // the client, and civetweb should not send client any more data.
414 return 1;
415}
416
417//////////////////////////////////////////////////////////////////////////
418// //
419// TCivetweb //
420// //
421// http server implementation, based on civetweb embedded server //
422// It is default kind of engine, created for THttpServer //
423// Currently v1.8 from https://github.com/civetweb/civetweb is used //
424// //
425// Following additional options can be specified: //
426// top=foldername - name of top folder, seen in the browser //
427// thrds=N - use N threads to run civetweb server (default 5) //
428// auth_file - global authentication file //
429// auth_domain - domain name, used for authentication //
430// //
431// Example: //
432// new THttpServer("http:8080?top=MyApp&thrds=3"); //
433// //
434// Authentication: //
435// When auth_file and auth_domain parameters are specified, access //
436// to running http server will be possible only after user //
437// authentication, using so-call digest method. To generate //
438// authentication file, htdigest routine should be used: //
439// //
440// [shell] htdigest -c .htdigest domain_name user //
441// //
442// When creating server, parameters should be: //
443// //
444// new THttpServer("http:8080?auth_file=.htdigets&auth_domain=domain_name"); //
445// //
446//////////////////////////////////////////////////////////////////////////
447
448////////////////////////////////////////////////////////////////////////////////
449/// constructor
450
452 : THttpEngine("civetweb", "compact embedded http server"), fCtx(nullptr), fCallbacks(nullptr), fTopName(),
453 fDebug(kFALSE), fTerminating(kFALSE), fOnlySecured(only_secured)
454{
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// destructor
459
461{
462 if (fCtx && !fTerminating)
463 mg_stop((struct mg_context *)fCtx);
464 if (fCallbacks)
466}
467
468////////////////////////////////////////////////////////////////////////////////
469/// process civetweb log message, can be used to detect critical errors
470
471Int_t TCivetweb::ProcessLog(const char *message)
472{
473 if ((gDebug > 0) || (strstr(message, "cannot bind to") != 0))
474 Error("Log", "%s", message);
475
476 return 0;
477}
478
479////////////////////////////////////////////////////////////////////////////////
480/// Creates embedded civetweb server
481/// As main argument, http port should be specified like "8090".
482/// Or one can provide combination of ipaddress and portnumber like 127.0.0.1:8090
483/// Extra parameters like in URL string could be specified after '?' mark:
484/// thrds=N - there N is number of threads used by the civetweb (default is 10)
485/// top=name - configure top name, visible in the web browser
486/// ssl_certificate=filename - SSL certificate, see docs/OpenSSL.md from civetweb
487/// auth_file=filename - authentication file name, created with htdigets utility
488/// auth_domain=domain - authentication domain
489/// websocket_timeout=tm - set web sockets timeout in seconds (default 300)
490/// websocket_disable - disable web sockets handling (default enabled)
491/// bind - ip address to bind server socket
492/// loopback - bind specified port to loopback 127.0.0.1 address
493/// debug - enable debug mode, server always returns html page with request info
494/// log=filename - configure civetweb log file
495/// max_age=value - configures "Cache-Control: max_age=value" http header for all file-related requests, default 3600
496/// nocache - try to fully disable cache control for file requests
497/// Examples:
498/// http:8080?websocket_disable
499/// http:7546?thrds=30&websocket_timeout=20
500
501Bool_t TCivetweb::Create(const char *args)
502{
503 fCallbacks = malloc(sizeof(struct mg_callbacks));
504 memset(fCallbacks, 0, sizeof(struct mg_callbacks));
505 //((struct mg_callbacks *) fCallbacks)->begin_request = begin_request_handler;
506 ((struct mg_callbacks *)fCallbacks)->log_message = log_message_handler;
507 TString sport = IsSecured() ? "8480s" : "8080", num_threads = "10", websocket_timeout = "300000";
508 TString auth_file, auth_domain, log_file, ssl_cert, max_age;
509 Bool_t use_ws = kTRUE;
510
511 // extract arguments
512 if (args && (strlen(args) > 0)) {
513
514 // first extract port number
515 sport = "";
516 while ((*args != 0) && (*args != '?') && (*args != '/'))
517 sport.Append(*args++);
518 if (IsSecured() && (sport.Index("s")==kNPOS)) sport.Append("s");
519
520 // than search for extra parameters
521 while ((*args != 0) && (*args != '?'))
522 args++;
523
524 if (*args == '?') {
525 TUrl url(TString::Format("http://localhost/folder%s", args));
526
527 if (url.IsValid()) {
528 url.ParseOptions();
529
530 const char *top = url.GetValueFromOptions("top");
531 if (top)
532 fTopName = top;
533
534 const char *log = url.GetValueFromOptions("log");
535 if (log)
536 log_file = log;
537
538 Int_t thrds = url.GetIntValueFromOptions("thrds");
539 if (thrds > 0)
540 num_threads.Form("%d", thrds);
541
542 const char *afile = url.GetValueFromOptions("auth_file");
543 if (afile)
544 auth_file = afile;
545
546 const char *adomain = url.GetValueFromOptions("auth_domain");
547 if (adomain)
548 auth_domain = adomain;
549
550 const char *sslc = url.GetValueFromOptions("ssl_cert");
551 if (sslc)
552 ssl_cert = sslc;
553
554 Int_t wtmout = url.GetIntValueFromOptions("websocket_timeout");
555 if (wtmout > 0) {
556 websocket_timeout.Format("%d", wtmout * 1000);
557 use_ws = kTRUE;
558 }
559
560 if (url.HasOption("websocket_disable"))
561 use_ws = kFALSE;
562
563 if (url.HasOption("debug"))
564 fDebug = kTRUE;
565
566 if (url.HasOption("loopback") && (sport.Index(":") == kNPOS))
567 sport = TString("127.0.0.1:") + sport;
568
569 if (url.HasOption("bind") && (sport.Index(":") == kNPOS)) {
570 const char *addr = url.GetValueFromOptions("bind");
571 if (addr && strlen(addr))
572 sport = TString(addr) + ":" + sport;
573 }
574
575 if (GetServer() && url.HasOption("cors")) {
576 const char *cors = url.GetValueFromOptions("cors");
577 GetServer()->SetCors(cors && *cors ? cors : "*");
578 }
579
580 if (url.HasOption("nocache"))
581 fMaxAge = 0;
582
583 if (url.HasOption("max_age"))
584 fMaxAge = url.GetIntValueFromOptions("max_age");
585
586 max_age.Form("%d", fMaxAge);
587 }
588 }
589 }
590
591 const char *options[20];
592 int op(0);
593
594 Info("Create", "Starting HTTP server on port %s", sport.Data());
595
596 options[op++] = "listening_ports";
597 options[op++] = sport.Data();
598 options[op++] = "num_threads";
599 options[op++] = num_threads.Data();
600
601 if (use_ws) {
602 options[op++] = "websocket_timeout_ms";
603 options[op++] = websocket_timeout.Data();
604 }
605
606 if ((auth_file.Length() > 0) && (auth_domain.Length() > 0)) {
607 options[op++] = "global_auth_file";
608 options[op++] = auth_file.Data();
609 options[op++] = "authentication_domain";
610 options[op++] = auth_domain.Data();
611 } else {
612 options[op++] = "enable_auth_domain_check";
613 options[op++] = "no";
614 }
615
616 if (log_file.Length() > 0) {
617 options[op++] = "error_log_file";
618 options[op++] = log_file.Data();
619 }
620
621 if (ssl_cert.Length() > 0) {
622 options[op++] = "ssl_certificate";
623 options[op++] = ssl_cert.Data();
624 } else if (IsSecured()) {
625 Error("Create", "No SSL certificate file configured");
626 }
627
628 if (max_age.Length() > 0) {
629 options[op++] = "static_file_max_age";
630 options[op++] = max_age.Data();
631 }
632
633 options[op++] = nullptr;
634
635 // Start the web server.
636 fCtx = mg_start((struct mg_callbacks *)fCallbacks, this, options);
637
638 if (!fCtx)
639 return kFALSE;
640
642
643 if (use_ws)
646
647 return kTRUE;
648}
const Ssiz_t kNPOS
Definition RtypesCore.h:124
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:101
bool Bool_t
Definition RtypesCore.h:63
const Bool_t kTRUE
Definition RtypesCore.h:100
int websocket_connect_handler(const struct mg_connection *conn, void *)
Definition TCivetweb.cxx:86
static int begin_request_handler(struct mg_connection *conn, void *)
static int log_message_handler(const struct mg_connection *conn, const char *message)
int websocket_data_handler(struct mg_connection *conn, int code, char *data, size_t len, void *)
void websocket_close_handler(const struct mg_connection *conn, void *)
void websocket_ready_handler(struct mg_connection *conn, void *)
char name[80]
Definition TGX11.cxx:110
#define INVALID_HANDLE_VALUE
Definition TMapFile.cxx:84
Int_t gDebug
Definition TROOT.cxx:592
#define BUFSIZE
const char * mime_type
Definition civetweb.c:7795
#define free
Definition civetweb.c:1539
int mg_printf(struct mg_connection *conn, const char *fmt,...)
Definition civetweb.c:6979
void mg_send_file(struct mg_connection *conn, const char *path)
Definition civetweb.c:9841
void mg_set_user_connection_data(struct mg_connection *conn, void *data)
Definition civetweb.c:3450
struct mg_context * mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **options)
Definition civetweb.c:18351
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:13395
void mg_send_mime_file(struct mg_connection *conn, const char *path, const char *mime_type)
Definition civetweb.c:9848
const char * mg_get_header(const struct mg_connection *conn, const char *name)
Definition civetweb.c:4016
int mg_write(struct mg_connection *conn, const void *buf, size_t len)
Definition civetweb.c:6755
const struct mg_request_info * mg_get_request_info(const struct mg_connection *conn)
Definition civetweb.c:3745
void * mg_get_user_connection_data(const struct mg_connection *conn)
Definition civetweb.c:3459
#define malloc
Definition civetweb.c:1536
int mg_read(struct mg_connection *conn, void *buf, size_t len)
Definition civetweb.c:6655
void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
Definition civetweb.c:13373
struct mg_context * mg_get_context(const struct mg_connection *conn)
Definition civetweb.c:3436
void mg_stop(struct mg_context *ctx)
Definition civetweb.c:18265
void * mg_get_user_data(const struct mg_context *ctx)
Definition civetweb.c:3443
CIVETWEB_API int mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
@ MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE
Definition civetweb.h:840
@ MG_WEBSOCKET_OPCODE_BINARY
Definition civetweb.h:839
@ MG_WEBSOCKET_OPCODE_TEXT
Definition civetweb.h:838
struct mg_connection * fWSconn
Definition TCivetweb.cxx:40
UInt_t GetId() const override
Definition TCivetweb.cxx:50
void SendCharStar(const char *str) override
Envelope for sending string via the websocket.
Definition TCivetweb.cxx:77
void ClearHandle(Bool_t terminate) override
Definition TCivetweb.cxx:52
Bool_t SupportSendThrd() const override
True websocket requires extra thread to parallelize sending.
Definition TCivetweb.cxx:43
void SendHeader(const char *hdr, const void *buf, int len) override
Special method to send binary data with text header For normal websocket it is two separated operatio...
Definition TCivetweb.cxx:69
void Send(const void *buf, int len) override
Definition TCivetweb.cxx:59
virtual ~TCivetwebWSEngine()=default
TCivetwebWSEngine(struct mg_connection *conn)
Definition TCivetweb.cxx:46
Bool_t IsTerminating() const
Definition TCivetweb.h:42
Int_t GetMaxAge() const
Definition TCivetweb.h:46
const char * GetTopName() const
Definition TCivetweb.h:38
void * fCtx
! civetweb context
Definition TCivetweb.h:20
TCivetweb(Bool_t only_secured=kFALSE)
constructor
Int_t fMaxAge
! max-age parameter
Definition TCivetweb.h:26
Int_t ProcessLog(const char *message)
process civetweb log message, can be used to detect critical errors
TString fTopName
! name of top item
Definition TCivetweb.h:22
Bool_t fTerminating
! server doing shutdown and not react on requests
Definition TCivetweb.h:24
Bool_t Create(const char *args) override
Creates embedded civetweb server As main argument, http port should be specified like "8090".
Bool_t IsSecured() const
Definition TCivetweb.h:30
Bool_t IsDebugMode() const
Definition TCivetweb.h:40
virtual ~TCivetweb()
destructor
Bool_t fDebug
! debug mode
Definition TCivetweb.h:23
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
Bool_t IsFileRequested(const char *uri, TString &res) const
Check if file is requested, thread safe.
Bool_t ExecuteWS(std::shared_ptr< THttpCallArg > &arg, Bool_t external_thrd=kFALSE, Bool_t wait_process=kFALSE)
Execute WS request.
Bool_t ExecuteHttp(std::shared_ptr< THttpCallArg > arg)
Execute HTTP request.
void SetCors(const std::string &domain="*")
Enable CORS header to ProcessRequests() responses Specified location (typically "*") add as "Access-C...
static char * ReadFileContent(const char *filename, Int_t &len)
Reads content of file from the disk.
static const char * GetMimeType(const char *path)
Guess mime type base on file extension.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:963
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:937
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:1946
const char * Data() const
Definition TString.h:369
@ kIgnoreCase
Definition TString.h:268
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition TString.cxx:662
TString & Append(const char *cs)
Definition TString.h:564
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:2336
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2314
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
Definition TUrl.cxx:659
Bool_t IsValid() const
Definition TUrl.h:79
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:671
void ParseOptions() const
Parse URL options into a key/value map.
Definition TUrl.cxx:625
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
Definition TUrl.cxx:682
const Int_t n
Definition legend1.C:16
const char * value
Definition civetweb.h:140
const char * name
Definition civetweb.h:139
struct mg_header http_headers[MG_MAX_HEADERS]
Definition civetweb.h:170
const char * local_uri
Definition civetweb.h:149
void * user_data
Definition civetweb.h:166
const char * request_method
Definition civetweb.h:146
const char * query_string
Definition civetweb.h:156
void * conn_data
Definition civetweb.h:167
const char * remote_user
Definition civetweb.h:158