NCBI C++ ToolKit
fcgiapp_mt.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: fcgiapp_mt.cpp 98307 2022-10-26 16:12:23Z grichenk $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Aleksey Grichenko
27 *
28 * File Description:
29 * Base class for multithreaded Fast-CGI applications
30 */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbienv.hpp>
34 #include <corelib/request_ctx.hpp>
35 #include <cgi/cgictx.hpp>
36 #include <cgi/cgi_exception.hpp>
37 #include <cgi/error_codes.hpp>
38 #include <cgi/fcgiapp_mt.hpp>
39 #include <util/cache/icache.hpp>
40 #include <util/multi_writer.hpp>
41 #include <signal.h>
42 
43 # if defined(NCBI_OS_UNIX)
44 # include <unistd.h>
45 #else
46 # include <io.h>
47 # endif
48 
49 
50 #define NCBI_USE_ERRCODE_X Cgi_Fast_MT
51 
52 
54 
55 
57 {
59  if (!app) return;
60  app->FASTCGI_ScheduleExit();
61  app->m_CaughtSigterm = true;
62 }
63 
64 
65 extern "C" void SignalHandler(int)
66 {
68 }
69 
70 
71 /////////////////////////////////////////////////////////////////////////////
72 // CFastCgiApplicationMT::
73 //
74 
76  : CCgiApplication(build_info),
77  m_ManagerStopped(false)
78 {
80 }
81 
82 
84 {
85 }
86 
87 
89 {
90  return dynamic_cast<CFastCgiApplicationMT*>(CCgiApplication::Instance());
91 }
92 
93 
94 DEFINE_STATIC_FAST_MUTEX(s_ManagerMutex);
95 
97 {
98  CFastMutexGuard guard(s_ManagerMutex);
99  if (!m_ManagerStopped) {
100  m_ManagerStopped = true;
101  m_Manager->stop();
102  }
103 }
104 
105 
106 bool CFastCgiApplicationMT::x_RunFastCGI(int* result, unsigned int def_iter)
107 {
108  // Reset the result (which is in fact an error counter here)
109  *result = 0;
110 
111  // Statistics
113  m_Stat.reset(m_IsStatLog ? CreateStat() : 0);
114 
115  // Max. number of the Fast-CGI loop iterations
117  bool handle_sigterm = GetFastCGIComplete_Request_On_Sigterm();
118 
119  // Watcher file -- to allow for stopping the Fast-CGI loop "prematurely"
122 
123 # ifndef USE_ALARM
124  if ( m_Watcher.get() || m_WatchTimeout ) {
125  ERR_POST_X(2, Warning << "[FastCGI].WatchFile.*** conf.parameter value(s) "
126  "specified, but this functionality is not supported");
127  }
128 # endif
129 
131 
133 
134  // Main Fast-CGI loop
136 
137  // Optionally turn on SIGTERM handler while processing request to allow
138  // the request to be completed before termination.
139  void (*old_sig_handler)(int) = SIG_DFL;
140  if (handle_sigterm) {
141  old_sig_handler = signal(SIGTERM, SignalHandler);
142  }
143 
144  TManager::setupSignals();
145  unsigned int max_threads = GetFastCGIMTMaxThreads();
146  m_Manager.reset(max_threads ? new TManager(max_threads) : new TManager());
147 
148  // If to run as a standalone server on local port or named socket
149  string path = GetFastCGIStandaloneServer();
150  if ( !path.empty() ) {
151 #ifdef NCBI_COMPILER_MSVC
152  _close(0);
153 #else
154  close(0);
155 #endif
156  // TODO: current fcgi uses path as a port or a name socket.
157  // Fastcgipp has different listen() methods for port/service and socket/path.
158  if (!m_Manager->listen(nullptr, path.c_str())) {
159  ERR_POST_X(1, "CFastCgiApplicationMT::x_RunFastCGI: cannot run as a "
160  "standalone server at: '" << path << "'");
161  }
162  }
163  else {
164  m_Manager->listen();
165  }
166  m_Manager->start();
167 
168  // Wait for all requests to be processed.
169  m_Manager->join();
171  x_OnEvent(nullptr, eExit, *result);
172 
173  // Reset SIGTERM handler to allow termination between requests.
174  if (handle_sigterm) {
175  signal(SIGTERM, old_sig_handler);
176  if (m_CaughtSigterm) {
177  ERR_POST(Message << "Caught SIGTERM and performed graceful shutdown.");
178  }
179  }
180 
181  _TRACE("CFastCgiApplicationMT::x_RunFastCGI: return (FastCGI loop finished)");
183  return true;
184 }
185 
187 
189 {
190  CAtomicCounter::TValue req_iter = m_Iteration.Add(1);
191 
192  CDiagContext& diag = GetDiagContext();
193 
194  SetDiagRequestId(req_iter);
196 
197  _TRACE("CFastCgiApplicationMT " << req_iter << " iteration of " << m_MaxIterations);
198 
199  // Process the request
201  bool skip_stat_log = false;
202 
203  CNcbiOstream* orig_stream = NULL;
204  CNcbiStrstream result_copy;
205  unique_ptr<CNcbiOstream> new_stream;
206 
207  shared_ptr<CCgiContext> context;
208  CCgiRequestProcessor& processor_base(x_CreateProcessor());
209  CCgiProcessorGuard proc_guard(*m_Processor);
210  CCgiRequestProcessorMT* processor = dynamic_cast<CCgiRequestProcessorMT*>(&processor_base);
211  _ASSERT(processor);
212 
213  try {
214  // Initialize CGI context with the new request data
215  CNcbiEnvironment env(req.env());
216  // Propagate environment values to PassThroughProperties.
218  list<string> names;
219  env.Enumerate(names);
220  ITERATE(list<string>, it, names) {
221  rctx.AddPassThroughProperty(*it, env.Get(*it));
222  }
223 
224  CNcbiArguments args(0, 0); // no cmd.-line ars
225 
226  context.reset(CreateContext(&args, &env, &req.in(), &req.out()));
227  _ASSERT(context);
228  context->CheckStatus();
229  processor->SetContext(context);
230 
231  // Checking for exit request (if explicitly allowed)
233  && context->GetRequest().GetEntries().find("exitfastcgi")
234  != context->GetRequest().GetEntries().end()) {
235  x_OnEvent(processor, eExitRequest, 114);
236  req.out() <<
237  "Content-Type: text/html" HTTP_EOL
238  HTTP_EOL
239  "Done";
240  _TRACE("CFastCgiApplicationMT aborting by request");
241  x_OnEvent(processor, eEndRequest, 122);
242  return;
243  }
244 
245  // Debug message (if requested)
246  if ( GetFastCGIDebug() ) {
247  context->PutMsg("FastCGI: " + NStr::NumericToString(m_Iteration.Get()) +
248  " iteration of " + NStr::NumericToString(m_MaxIterations) +
250  }
251 
252  AddLBCookie(context->GetResponse().Cookies());
253 
254  // Call ProcessRequest()
255  x_OnEvent(processor, eStartRequest, 0);
256  _TRACE("CFastCgiApplicationMT calling ProcessRequest()");
257 
259  string self_ref = processor->GetSelfReferer();
260  if ( !self_ref.empty() ) {
261  CDiagContext::GetRequestContext().SetProperty("SELF_URL", self_ref);
262  }
264 
265  int x_result = 0;
266  shared_ptr<ICache> cache;
267  try {
268  try {
269  cache.reset( GetCacheStorage() );
270  }
271  NCBI_CATCH_ALL_X(1, "Couldn't create cache")
272  bool skip_process_request = false;
273  bool caching_needed = IsCachingNeeded(context->GetRequest());
274  if (cache.get() && caching_needed) {
275  skip_process_request = GetResultFromCache(context->GetRequest(),
276  context->GetResponse().out(), *cache);
277  }
278 
279  if (!skip_process_request) {
280  if( cache ) {
281  CCgiStreamWrapper* wrapper =
282  dynamic_cast<CCgiStreamWrapper*>(context->GetResponse().GetOutput());
283  if ( wrapper ) {
284  wrapper->SetCacheStream(result_copy);
285  }
286  else {
287  list<CNcbiOstream*> slist;
288  orig_stream = context->GetResponse().GetOutput();
289  slist.push_back(orig_stream);
290  slist.push_back(&result_copy);
291  new_stream.reset(new CWStream(new CMultiWriter(slist), 1, 0, CRWStreambuf::fOwnWriter));
292  context->GetResponse().SetOutput(new_stream.get());
293  }
294  }
296  if (x_ProcessHelpRequest(*processor) ||
297  x_ProcessVersionRequest(*processor) ||
298  CCgiContext::ProcessCORSRequest(context->GetRequest(), context->GetResponse()) ||
299  x_ProcessAdminRequest(*processor)) {
300  x_result = 0;
301  }
302  else {
303  if (!processor->ValidateSynchronizationToken()) {
305  "Invalid or missing CSRF token.", CCgiException::e403_Forbidden);
306  }
307  x_result = processor->ProcessRequest(*context);
308  }
310  context->GetResponse().Finalize();
311  if (x_result == 0) {
312  if ( cache ) {
313  context->GetResponse().Flush();
314  if (processor->GetResultReady()) {
315  if(caching_needed)
316  SaveResultToCache(context->GetRequest(), result_copy, *cache);
317  else {
318  unique_ptr<CCgiRequest> saved_request(GetSavedRequest(processor->GetRID(), *cache));
319  if (saved_request.get())
320  SaveResultToCache(*saved_request, result_copy, *cache);
321  }
322  } else if (caching_needed) {
323  SaveRequest(processor->GetRID(), context->GetRequest(), *cache);
324  }
325  }
326  }
327  }
328  }
329  catch (CCgiException& e) {
333  throw;
334  }
335  // If for some reason exception with status 2xx was thrown,
336  // set the result to 0, update HTTP status and continue.
337  context->GetResponse().SetStatus(e.GetStatusCode(), e.GetStatusMessage());
338  x_result = 0;
339  }
340  catch (exception&) {
341  // Remember byte counts before the streams are destroyed.
344  throw;
345  }
347  _TRACE("CFastCgiApplicationMT flushing");
348  context->GetResponse().Flush();
349  _TRACE("CFastCgiApplicationMT: done, status: " << x_result);
350  if (x_result != 0) m_ErrorCounter.Add(1);
353  x_OnEvent(processor, x_result == 0 ? eSuccess : eError, x_result);
354  context->GetResponse().SetOutput(0);
355  context->GetRequest().SetInputStream(0);
356  }
357  catch (exception& e) {
358  // Reset stream pointers since the streams have been destroyed.
359  try {
360  CNcbiOstream* os = context->GetResponse().GetOutput();
361  if (os && !os->good()) {
362  processor->SetOutputBroken(true);
363  }
364  }
365  catch (exception&) {
366  }
367  context->GetResponse().SetOutput(0);
368  context->GetRequest().SetInputStream(0);
369 
371  // Increment error counter
372  m_ErrorCounter.Add(1);
373 
374  // Call the exception handler and set the CGI exit code
375  int exit_code = processor->OnException(e, req.out());
376  x_OnEvent(processor, eException, exit_code);
377 
378  // Logging
379  {{
380  string msg = "CCgiRequestProcessorMT::ProcessRequest() failed: ";
381  msg += e.what();
382  if ( m_IsStatLog ) {
383  m_Stat->Reset(start_time, m_ErrorCounter.Get(), &e);
384  msg = m_Stat->Compose();
385  m_Stat->Submit(msg);
386  skip_stat_log = true; // Don't print the same message again
387  }
388  }}
389 
390  // Exception reporting
391  NCBI_REPORT_EXCEPTION_X(4, "CCgiRequestProcessorMT::ProcessRequest", e);
392 
393  // (If to) abrupt the FCGI loop on error
394  if ( m_StopIfFailed ) { // configured to stop on error
395  // close current request
396  x_OnEvent(processor, eExitOnFail, 113);
397  _TRACE("CCgiApplication::x_RunFastCGI: FINISHING(forced)");
398  x_OnEvent(processor, eEndRequest, 123);
400  return;
401  }
402  }
404 
405  // Close current request
406  _TRACE("CCgiRequestProcessor::x_ProcessThreadedRequest: FINISHING");
407 
408  // Logging
409  if ( m_IsStatLog && !skip_stat_log ) {
410  m_Stat->Reset(start_time, m_ErrorCounter.Get());
411  string msg = m_Stat->Compose();
412  m_Stat->Submit(msg);
413  }
414 
415  //
416  x_OnEvent(processor, eEndRequest, 121);
417 
418  if ( req_iter >= m_MaxIterations || CheckMemoryLimit() ) {
420  return;
421  }
422 
423  // If to restart the application
424  int restart_code = ShouldRestart(m_ModTime, m_Watcher.get(), m_RestartDelay);
425  if (restart_code != 0) {
426  x_OnEvent(processor, restart_code == eSR_Executable ?
427  eExecutable : eWatchFile, restart_code);
428  m_ErrorCounter.Set((restart_code == eSR_WatchFile) ? 0 : restart_code);
430  return;
431  }
432 
433  // Run idler when finished. By default this reopens log file(s).
434  {
435  CFastMutexGuard guard(s_IdlerMutex);
436  RunIdler();
437  }
438 }
439 
440 
441 /////////////////////////////////////////////////////////////////////////////
442 // CFastCgiThreadedRequest::
443 //
444 
446 {
447 }
448 
449 
451 {
452 }
453 
454 
456 {
458  _ASSERT(app);
459  app->x_ProcessThreadedRequest(*this);
460  return true;
461 }
462 
463 
465 {
466  ERR_POST_X(5, "Internal fastcgi++ error");
467  Fastcgipp::Request<char>::errorHandler();
468 }
469 
470 
472 {
473  // raw post data is fully assembled in environment().postBuffer() and the type string is stored in environment().contentType
474  // return true if the data has been processed, false to let the library process it as std POST.
475  const auto& buf = environment().postBuffer();
476  m_InputStream.reset(new stringstream(string(buf.data(), buf.size())));
477  return false;
478 }
479 
480 
482 {
483  const auto& env = environment();
484 
485  if ( !env.host.empty() ) m_Env.Set("HTTP_HOST", env.host);
486  if ( !env.origin.empty() ) m_Env.Set("HTTP_ORIGIN", env.origin);
487  if ( !env.userAgent.empty() ) m_Env.Set("HTTP_USER_AGENT", env.userAgent);
488  if ( !env.acceptContentTypes.empty() ) m_Env.Set("HTTP_ACCEPT", env.acceptContentTypes);
489  if ( !env.acceptCharsets.empty() ) m_Env.Set("HTTP_ACCEPT_CHARSET", env.acceptCharsets);
490  if ( !env.authorization.empty() ) m_Env.Set("HTTP_AUTHORIZATION", env.authorization);
491  if ( !env.referer.empty() ) m_Env.Set("HTTP_REFERER", env.referer);
492  if ( !env.contentType.empty() ) m_Env.Set("CONTENT_TYPE", env.contentType);
493  if ( !env.root.empty() ) m_Env.Set("DOCUMENT_ROOT", env.root);
494  if ( !env.scriptName.empty() ) m_Env.Set("SCRIPT_NAME", env.scriptName);
495  if ( !env.requestUri.empty() ) m_Env.Set("REQUEST_URI", env.requestUri);
496 
497  if ( env.etag ) m_Env.Set("HTTP_IF_NONE_MATCH", NStr::NumericToString(env.etag)); // unsigned
498  if ( env.keepAlive ) m_Env.Set("HTTP_KEEP_ALIVE", NStr::NumericToString(env.keepAlive)); // unsigned
499  if ( env.contentLength ) m_Env.Set("CONTENT_LENGTH", NStr::NumericToString(env.contentLength)); // unsigned
500  if ( env.serverPort ) m_Env.Set("SERVER_PORT", NStr::NumericToString(env.serverPort)); // uint16_t
501  if ( env.remotePort ) m_Env.Set("REMOTE_PORT", NStr::NumericToString(env.remotePort)); // uint16_t
502 
503  switch (env.requestMethod) {
504  case Fastcgipp::Http::RequestMethod::HEAD: m_Env.Set("REQUEST_METHOD", "HEAD"); break;
505  case Fastcgipp::Http::RequestMethod::GET: m_Env.Set("REQUEST_METHOD", "GET"); break;
506  case Fastcgipp::Http::RequestMethod::POST: m_Env.Set("REQUEST_METHOD", "POST"); break;
507  case Fastcgipp::Http::RequestMethod::PUT: m_Env.Set("REQUEST_METHOD", "PUT"); break;
508  case Fastcgipp::Http::RequestMethod::DELETE: m_Env.Set("REQUEST_METHOD", "DELETE"); break;
509  case Fastcgipp::Http::RequestMethod::TRACE: m_Env.Set("REQUEST_METHOD", "TRACE"); break;
510  case Fastcgipp::Http::RequestMethod::OPTIONS: m_Env.Set("REQUEST_METHOD", "OPTIONS"); break;
511  case Fastcgipp::Http::RequestMethod::CONNECT: m_Env.Set("REQUEST_METHOD", "CONNECT"); break;
512  default:
513  ERR_POST_X(3, "REQUEST_METHOD not set or not supported");
514  break;
515  }
516 
517  if ( env.serverAddress ) {
518  stringstream buf;
519  buf << env.serverAddress;
520  m_Env.Set("SERVER_ADDR", buf.str());
521  }
522 
523  if ( env.remoteAddress ) {
524  stringstream buf;
525  buf << env.remoteAddress;
526  m_Env.Set("REMOTE_ADDR", buf.str());
527  }
528 
529  if ( env.ifModifiedSince ) { // time_t, "%a, %d %b %Y %H:%M:%S GMT"
530  CTime t(env.ifModifiedSince);
531  CTimeFormat fmt("w, D b Y h:m:s Z");
532  m_Env.Set("HTTP_IF_MODIFIED_SINCE", t.AsString(fmt, CTime::eGmt));
533  }
534 
535  // NOTE: fastcgipp does not store language qualities, only names.
536  string languages;
537  for (const auto& lang : env.acceptLanguages) {
538  if (!languages.empty()) languages += ", ";
539  languages += NStr::Replace(lang, "_", "-");
540  }
541  if ( !languages.empty() ) m_Env.Set("HTTP_ACCEPT_LANGUAGE", languages);
542 
543  // NOTE: The restored PATH_INFO may be missing empty elements (double slashes) and the trailing slash.
544  string path_info;
545  for (const auto& element : env.pathInfo) {
546  path_info += "/" + NStr::URLEncode(element, NStr::eUrlEnc_Path);
547  }
548  m_Env.Set("PATH_INFO", path_info);
549 
550  if (!env.cookies.empty()) {
551  string cookies;
552  for (const auto& cookie : env.cookies) {
553  if (!cookies.empty()) cookies += "; ";
554  cookies += NStr::URLEncode(cookie.first, NStr::eUrlEnc_Cookie) + "="
555  + NStr::URLEncode(cookie.second, NStr::eUrlEnc_Cookie);
556  }
557  m_Env.Set("HTTP_COOKIE", cookies);
558  }
559 
560  if (!env.gets.empty()) {
561  string query;
562  for (const auto& arg : env.gets) {
563  if (!query.empty()) query += '&';
566  }
567  m_Env.Set("QUERY_STRING", query);
568  }
569 
570  for (const auto& it : env.others) {
571  m_Env.Set(it.first, it.second);
572  }
573  m_Env.data.push_back(nullptr);
574 }
575 
576 
577 /////////////////////////////////////////////////////////////////////////////
578 // CMTCgiRequestProcessor_Base::
579 //
580 
581 
583  : CCgiRequestProcessor(app)
584 {
585  // NOTE: This creates a new instance of resource in every request processor.
586  // It could be better to have just one copy, but the existing resources are
587  // not MT-safe.
588  m_Resource.reset(GetApp().LoadResource());
589 }
590 
591 
593 {
594 }
595 
596 
Exception classes used by the NCBI CGI framework.
CCgiRequestException –.
Base class for request processors.
Definition: cgiapp.hpp:579
IWriter which can write simultaneously to the different streams.
CNcbiArguments –.
Definition: ncbienv.hpp:236
CNcbiEnvironment –.
Definition: ncbienv.hpp:110
@ fOwnWriter
Own the underlying writer.
Definition: rwstreambuf.hpp:67
CTimeFormat –.
Definition: ncbitime.hpp:131
CTime –.
Definition: ncbitime.hpp:296
Writer-based output stream.
Definition: rwstream.hpp:171
int close(int fd)
Definition: connection.cpp:45
DEFINE_STATIC_FAST_MUTEX(s_ManagerMutex)
void s_ScheduleFastCGIMTExit(void)
Definition: fcgiapp_mt.cpp:56
void SignalHandler(int)
Definition: fcgiapp_mt.cpp:65
static const struct name_t names[]
static time_t start_time
Definition: timeout.c:14
#define false
Definition: bool.h:36
static HENV env
Definition: transaction2.c:38
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
const CNcbiArguments & GetArguments(void) const
Get the application's cached unprocessed command-line arguments.
void RunIdler(void)
Execute currently installed idler if any.
Definition: ncbiapp.cpp:1851
unsigned int GetFastCGIWatchFileTimeout(bool have_watcher) const
Definition: cgiapp.cpp:1901
virtual ~CCgiRequestProcessorMT(void)
Definition: fcgiapp_mt.cpp:592
void SetOutputBroken(bool val)
Definition: cgiapp.hpp:655
unique_ptr< CCgiStatistics > m_Stat
Definition: fcgiapp_mt.hpp:135
bool GetFastCGIComplete_Request_On_Sigterm(void) const
Definition: cgiapp.cpp:1874
bool CheckMemoryLimit(void)
Definition: cgiapp.cpp:1971
CCgiRequestProcessorMT(CFastCgiApplicationMT &app)
Definition: fcgiapp_mt.cpp:582
bool x_RunFastCGI(int *result, unsigned int def_iter=10) override
Definition: fcgiapp_mt.cpp:106
unsigned int GetFastCGIIterations(unsigned int def_iter) const
Definition: cgiapp.cpp:1848
unsigned int GetFastCGIMTMaxThreads(void) const
Definition: cgiapp.cpp:1950
CAtomicCounter m_Iteration
Definition: cgiapp.hpp:434
int GetFastCGIWatchFileRestartDelay(void) const
Definition: cgiapp.cpp:1915
virtual int ProcessRequest(CCgiContext &context)
Process request provided by the context. By default calls application's ProcessRequest.
Definition: cgiapp.cpp:2263
static CTime GetFileModificationTime(const string &filename)
Definition: cgiapp.cpp:1959
bool GetFastCGIStatLog(void) const
Definition: cgiapp.cpp:1842
void SetCacheStream(CNcbiOstream &stream)
Definition: cgiapp.cpp:434
CFastCgiApplicationMT(const SBuildInfo &build_info=NCBI_SBUILDINFO_DEFAULT())
Definition: fcgiapp_mt.cpp:75
bool GetFastCGIStopIfFailed(void) const
Definition: cgiapp.cpp:1944
static bool ProcessCORSRequest(const CCgiRequest &request, CCgiResponse &response)
Process cross-origin resource sharing (CORS) request.
Definition: cgictx.cpp:839
bool x_ProcessHelpRequest(CCgiRequestProcessor &processor)
Definition: cgiapp.cpp:1695
Fastcgipp::Manager< CFastCgiThreadedRequest > TManager
Definition: fcgiapp_mt.hpp:130
unique_ptr< TManager > m_Manager
Definition: fcgiapp_mt.hpp:132
TOutput & out(void)
Definition: fcgiapp_mt.hpp:70
string GetFastCGIStandaloneServer(void) const
Definition: cgiapp.cpp:1829
static ERestartReason ShouldRestart(CTime &mtime, CCgiWatchFile *watcher, int delay)
Definition: cgiapp.cpp:1994
unsigned int m_WatchTimeout
Definition: fcgiapp_mt.hpp:138
void Set(const string &name, const string &value)
Definition: fcgiapp_mt.hpp:89
bool x_ProcessAdminRequest(CCgiRequestProcessor &processor)
Definition: cgiapp.cpp:1781
virtual CCgiContext * CreateContext(CNcbiArguments *args=0, CNcbiEnvironment *env=0, CNcbiIstream *inp=0, CNcbiOstream *out=0, int ifd=-1, int ofd=-1)
Factory method for the Context object construction.
Definition: cgiapp.cpp:900
void x_OnEvent(CCgiRequestProcessor *pprocessor, EEvent event, int status)
Definition: cgiapp.cpp:1073
virtual ICache * GetCacheStorage(void) const
Definition: cgiapp.cpp:1381
unique_ptr< CNcbiResource > m_Resource
Definition: fcgiapp_mt.hpp:159
virtual int OnException(std::exception &e, CNcbiOstream &os)
Definition: cgiapp.cpp:2482
unique_ptr< CCgiWatchFile > m_Watcher
Definition: fcgiapp_mt.hpp:137
virtual bool ValidateSynchronizationToken(void)
Definition: cgiapp.cpp:2456
CCgiApplication & GetApp(void)
Definition: cgiapp.hpp:632
string GetRID(void) const
Definition: cgiapp.hpp:663
void errorHandler(void) override
Definition: fcgiapp_mt.cpp:464
virtual bool IsCachingNeeded(const CCgiRequest &request) const
Definition: cgiapp.cpp:1375
virtual CCgiStatistics * CreateStat()
Class factory for statistics class.
Definition: cgiapp.cpp:1362
void SaveResultToCache(const CCgiRequest &request, CNcbiIstream &is, ICache &cache)
Definition: cgiapp.cpp:1439
bool x_ProcessVersionRequest(CCgiRequestProcessor &processor)
Definition: cgiapp.cpp:1731
void SetContext(shared_ptr< CCgiContext > context)
Definition: cgiapp.hpp:637
void SaveRequest(const string &rid, const CCgiRequest &request, ICache &cache)
Definition: cgiapp.cpp:1458
CAtomicCounter m_ErrorCounter
Definition: fcgiapp_mt.hpp:133
void FASTCGI_ScheduleExit(void) override
Schedule Fast-CGI loop to end as soon as possible, after safely finishing the currently processed req...
Definition: fcgiapp_mt.cpp:96
static CCgiApplication * Instance(void)
Singleton.
Definition: cgiapp.cpp:457
bool inProcessor(void) override
Definition: fcgiapp_mt.cpp:471
CCgiRequestProcessor & x_CreateProcessor(void)
Definition: cgiapp.cpp:851
CCgiRequest * GetSavedRequest(const string &rid, ICache &cache)
Definition: cgiapp.cpp:1474
string GetSelfReferer(void) const
Get self-URL to be used as referer.
Definition: cgiapp.cpp:2465
const char *const * env(void) const
Definition: fcgiapp_mt.hpp:72
CRef< CTls< CCgiRequestProcessor > > m_Processor
Definition: cgiapp.hpp:433
void x_ParseEnv(void) const
Definition: fcgiapp_mt.cpp:481
shared_ptr< istream > m_InputStream
Definition: fcgiapp_mt.hpp:97
void x_ProcessThreadedRequest(CFastCgiThreadedRequest &req)
Definition: fcgiapp_mt.cpp:188
bool GetFastCGIDebug(void) const
Definition: cgiapp.cpp:1938
CCgiWatchFile * CreateFastCGIWatchFile(void) const
Definition: cgiapp.cpp:1880
bool m_CaughtSigterm
Definition: cgiapp.hpp:432
bool response(void) override
Definition: fcgiapp_mt.cpp:455
unsigned int m_MaxIterations
Definition: fcgiapp_mt.hpp:136
bool GetResultReady(void) const
Definition: cgiapp.hpp:666
bool GetResultFromCache(const CCgiRequest &request, CNcbiOstream &os, ICache &cache)
Definition: cgiapp.cpp:1418
void LogRequest(void) const
Definition: cgiapp.cpp:715
bool GetFastCGIHonorExitRequest(void) const
Definition: cgiapp.cpp:1933
void VerifyCgiContext(CCgiContext &context)
Check CGI context for possible problems, throw exception with HTTP status set if something is wrong.
Definition: cgiapp.cpp:1561
void AddLBCookie(CCgiCookies &cookies)
Definition: cgiapp.cpp:1493
static CFastCgiApplicationMT * Instance(void)
Singleton.
Definition: fcgiapp_mt.cpp:88
@ eException
An exception occured during the request processing.
Definition: cgiapp.hpp:193
@ eExitRequest
FCGI forced to exit by client's 'exitfastcgi' request.
Definition: cgiapp.hpp:199
@ eExit
No more iterations, exiting (called the very last)
Definition: cgiapp.hpp:195
@ eError
The HTTP request was processed, non-zero exit code.
Definition: cgiapp.hpp:191
@ eEndRequest
HTTP request processed, all results sent to client.
Definition: cgiapp.hpp:194
@ eExecutable
FCGI forced to exit as its modif. time has changed.
Definition: cgiapp.hpp:196
@ eWatchFile
FCGI forced to exit as its "watch file" has changed.
Definition: cgiapp.hpp:197
@ eExitOnFail
[FastCGI].StopIfFailed set, and the iteration failed
Definition: cgiapp.hpp:198
@ eSuccess
The HTTP request was processed, with zero exit code.
Definition: cgiapp.hpp:190
#define NCBI_CGI_THROW_WITH_STATUS(exception, err_code, message, status)
EStatusCode GetStatusCode(void) const
string GetStatusMessage(void) const
#define NULL
Definition: ncbistd.hpp:225
TNCBIAtomicValue TValue
Alias TValue for TNCBIAtomicValue.
Definition: ncbicntr.hpp:73
void Set(TValue new_value) THROWS_NONE
Set atomic counter value.
Definition: ncbicntr.hpp:185
TValue Add(int delta) THROWS_NONE
Atomically add value (=delta), and return new counter value.
Definition: ncbicntr.hpp:278
TValue Get(void) const THROWS_NONE
Get atomic counter value.
Definition: ncbicntr.hpp:168
#define _TRACE(message)
Definition: ncbidbg.hpp:122
void SetBytesWr(Int8 bytes)
CDiagContext & GetDiagContext(void)
Get diag context instance.
Definition: logging.cpp:818
void SetAppState(EDiagAppState state)
Set application state.
Definition: ncbidiag.cpp:2815
void SetDiagRequestId(Uint8 id)
Set iteration number/request ID.
Definition: ncbidiag.cpp:1201
void SetProperty(const string &name, const string &value)
Add/change property.
static CRequestContext & GetRequestContext(void)
Shortcut to CDiagContextThreadData::GetThreadData().GetRequestContext()
Definition: ncbidiag.cpp:1901
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
void SetBytesRd(Int8 bytes)
void AddPassThroughProperty(const string &name, const string &value)
Add pass-through value if it matches a pattern from NCBI_CONTEXT_FIELDS.
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
@ eDiagAppState_RequestEnd
RE.
Definition: ncbidiag.hpp:796
@ eDiagAppState_AppEnd
AE.
Definition: ncbidiag.hpp:793
@ eDiagAppState_RequestBegin
RB.
Definition: ncbidiag.hpp:794
@ eDiagAppState_Request
R.
Definition: ncbidiag.hpp:795
#define NCBI_CATCH_ALL_X(err_subcode, message)
Definition: ncbiexpt.hpp:619
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
#define NCBI_REPORT_EXCEPTION_X(err_subcode, title, ex)
Generate a report on the exception with default error code and given subcode.
Definition: ncbiexpt.hpp:761
static TPid GetPid(void)
Get process identifier (pid) for the current process.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
Int8 NcbiStreamposToInt8(NCBI_NS_STD::char_traits< char >::pos_type stream_pos)
Convert stream position to 64-bit int.
Definition: ncbistre.hpp:771
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
static string & Replace(const string &src, const string &search, const string &replace, string &dst, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3314
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static string URLEncode(const CTempString str, EUrlEncode flag=eUrlEnc_SkipMarkChars)
URL-encode string.
Definition: ncbistr.cpp:6062
@ eUrlEnc_URIQueryValue
Encode query part of an URI, arg value.
Definition: ncbistr.hpp:3151
@ eUrlEnc_URIQueryName
Encode query part of an URI, arg name.
Definition: ncbistr.hpp:3150
@ eUrlEnc_Path
Same as ProcessMarkChars but preserves valid path characters ('/', '.')
Definition: ncbistr.hpp:3145
@ eUrlEnc_Cookie
Same as SkipMarkChars with encoded ','.
Definition: ncbistr.hpp:3153
@ eCurrent
Use current time. See also CCurrentTime.
Definition: ncbitime.hpp:300
@ eGmt
GMT (Greenwich Mean Time)
Definition: ncbitime.hpp:308
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
Interfaces for a local cache of versioned binary large objects (BLOBS).
Definition of all error codes used in cgi (xcgi.lib).
char * buf
EIPRangeType t
Definition: ncbi_localip.c:101
Defines unified interface to application:
#define GetProgramName
Avoid name clash with the NCBI C Toolkit.
Definition: ncbienv.hpp:49
#define HTTP_EOL
Definition: ncbistre.hpp:120
Defines CRequestContext class for NCBI C++ diagnostic API.
This class allows to add build info (date and tag) to application version.
Definition: version_api.hpp:62
static string query
#define _ASSERT
else result
Definition: token2.c:20
static CS_CONTEXT * context
Definition: will_convert.c:21
@ HEAD
Definition: inflate.h:21
Modified on Tue May 28 05:50:53 2024 by modify_doxy.py rev. 669887