QGIS API Documentation  3.25.0-Master (10b47c2603)
qgsserver.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsserver.cpp
3  A server application supporting WMS / WFS / WCS
4  -------------------
5  begin : July 04, 2006
6  copyright : (C) 2006 by Marco Hugentobler & Ionut Iosifescu Enescu
7  : (C) 2015 by Alessandro Pasotti
8  email : marco dot hugentobler at karto dot baug dot ethz dot ch
9  : elpaso at itopen dot it
10  ***************************************************************************/
11 
12 /***************************************************************************
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  ***************************************************************************/
20 
21 //for CMAKE_INSTALL_PREFIX
22 #include "qgsconfig.h"
23 #include "qgsversion.h"
24 #include "qgsserver.h"
25 #include "qgsauthmanager.h"
26 #include "qgscapabilitiescache.h"
27 #include "qgsfontutils.h"
28 #include "qgsrequesthandler.h"
29 #include "qgsproject.h"
30 #include "qgsproviderregistry.h"
31 #include "qgslogger.h"
32 #include "qgsmapserviceexception.h"
34 #include "qgsserverlogger.h"
35 #include "qgsserverrequest.h"
37 #include "qgsservice.h"
38 #include "qgsserverapi.h"
39 #include "qgsserverapicontext.h"
40 #include "qgsserverparameters.h"
41 #include "qgsapplication.h"
42 #include "qgsruntimeprofiler.h"
43 #include "qgscoordinatetransform.h"
44 
45 #include <QDomDocument>
46 #include <QNetworkDiskCache>
47 #include <QSettings>
48 #include <QElapsedTimer>
49 
50 // TODO: remove, it's only needed by a single debug message
51 #include <fcgi_stdio.h>
52 #include <cstdlib>
53 
54 
55 // Server status static initializers.
56 // Default values are for C++, SIP bindings will override their
57 // options in in init()
58 
59 QString *QgsServer::sConfigFilePath = nullptr;
60 QgsCapabilitiesCache *QgsServer::sCapabilitiesCache = nullptr;
61 QgsServerInterfaceImpl *QgsServer::sServerInterface = nullptr;
62 // Initialization must run once for all servers
63 bool QgsServer::sInitialized = false;
64 
65 QgsServiceRegistry *QgsServer::sServiceRegistry = nullptr;
66 
68 
70 {
71  // QgsApplication must exist
72  if ( qobject_cast<QgsApplication *>( qApp ) == nullptr )
73  {
74  qFatal( "A QgsApplication must exist before a QgsServer instance can be created." );
75  abort();
76  }
77  init();
78  mConfigCache = QgsConfigCache::instance();
79 }
80 
81 QFileInfo QgsServer::defaultAdminSLD()
82 {
83  return QFileInfo( QStringLiteral( "admin.sld" ) );
84 }
85 
86 void QgsServer::setupNetworkAccessManager()
87 {
88  const QSettings settings;
90  QNetworkDiskCache *cache = new QNetworkDiskCache( nullptr );
91  const qint64 cacheSize = sSettings()->cacheSize();
92  const QString cacheDirectory = sSettings()->cacheDirectory();
93  cache->setCacheDirectory( cacheDirectory );
94  cache->setMaximumCacheSize( cacheSize );
95  QgsMessageLog::logMessage( QStringLiteral( "cacheDirectory: %1" ).arg( cache->cacheDirectory() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
96  QgsMessageLog::logMessage( QStringLiteral( "maximumCacheSize: %1" ).arg( cache->maximumCacheSize() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
97  nam->setCache( cache );
98 }
99 
100 QFileInfo QgsServer::defaultProjectFile()
101 {
102  const QDir currentDir;
103  fprintf( FCGI_stderr, "current directory: %s\n", currentDir.absolutePath().toUtf8().constData() );
104  QStringList nameFilterList;
105  nameFilterList << QStringLiteral( "*.qgs" )
106  << QStringLiteral( "*.qgz" );
107  const QFileInfoList projectFiles = currentDir.entryInfoList( nameFilterList, QDir::Files, QDir::Name );
108  for ( int x = 0; x < projectFiles.size(); x++ )
109  {
110  QgsMessageLog::logMessage( projectFiles.at( x ).absoluteFilePath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
111  }
112  if ( projectFiles.isEmpty() )
113  {
114  return QFileInfo();
115  }
116  return projectFiles.at( 0 );
117 }
118 
119 void QgsServer::printRequestParameters( const QMap< QString, QString> &parameterMap, Qgis::MessageLevel logLevel )
120 {
121  if ( logLevel > Qgis::MessageLevel::Info )
122  {
123  return;
124  }
125 
126  QMap< QString, QString>::const_iterator pIt = parameterMap.constBegin();
127  for ( ; pIt != parameterMap.constEnd(); ++pIt )
128  {
129  QgsMessageLog::logMessage( pIt.key() + ":" + pIt.value(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
130  }
131 }
132 
133 QString QgsServer::configPath( const QString &defaultConfigPath, const QString &configPath )
134 {
135  QString cfPath( defaultConfigPath );
136  const QString projectFile = sSettings()->projectFile();
137  if ( !projectFile.isEmpty() )
138  {
139  cfPath = projectFile;
140  QgsDebugMsg( QStringLiteral( "QGIS_PROJECT_FILE:%1" ).arg( cfPath ) );
141  }
142  else
143  {
144  if ( configPath.isEmpty() )
145  {
146  // Read it from the environment, because a rewrite rule may have rewritten it
147  if ( getenv( "QGIS_PROJECT_FILE" ) )
148  {
149  cfPath = getenv( "QGIS_PROJECT_FILE" );
150  QgsMessageLog::logMessage( QStringLiteral( "Using configuration file path from environment: %1" ).arg( cfPath ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
151  }
152  else if ( ! defaultConfigPath.isEmpty() )
153  {
154  QgsMessageLog::logMessage( QStringLiteral( "Using default configuration file path: %1" ).arg( defaultConfigPath ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
155  }
156  }
157  else
158  {
159  cfPath = configPath;
160  QgsDebugMsg( QStringLiteral( "MAP:%1" ).arg( cfPath ) );
161  }
162  }
163  return cfPath;
164 }
165 
166 void QgsServer::initLocale()
167 {
168  // System locale override
169  if ( ! sSettings()->overrideSystemLocale().isEmpty() )
170  {
171  QLocale::setDefault( QLocale( sSettings()->overrideSystemLocale() ) );
172  }
173  // Number group separator settings
174  QLocale currentLocale;
175  if ( sSettings()->showGroupSeparator() )
176  {
177  currentLocale.setNumberOptions( currentLocale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
178  }
179  else
180  {
181  currentLocale.setNumberOptions( currentLocale.numberOptions() |= QLocale::NumberOption::OmitGroupSeparator );
182  }
183  QLocale::setDefault( currentLocale );
184 }
185 
186 bool QgsServer::init()
187 {
188  if ( sInitialized )
189  {
190  return false;
191  }
192 
193  QCoreApplication::setOrganizationName( QgsApplication::QGIS_ORGANIZATION_NAME );
194  QCoreApplication::setOrganizationDomain( QgsApplication::QGIS_ORGANIZATION_DOMAIN );
195  QCoreApplication::setApplicationName( QgsApplication::QGIS_APPLICATION_NAME );
196 
197  // TODO: remove QGIS_OPTIONS_PATH from settings and rely on QgsApplication's env var QGIS_CUSTOM_CONFIG_PATH
198  // Note that QGIS_CUSTOM_CONFIG_PATH gives /tmp/qt_temp-rUpsId/profiles/default/QGIS/QGIS3.ini
199  // while QGIS_OPTIONS_PATH gives /tmp/qt_temp-rUpsId/QGIS/QGIS3.ini
200  QgsApplication::init( qgetenv( "QGIS_OPTIONS_PATH" ) );
201 
202 #if defined(SERVER_SKIP_ECW)
203  QgsMessageLog::logMessage( "Skipping GDAL ECW drivers in server.", "Server", Qgis::MessageLevel::Info );
205  QgsApplication::skipGdalDriver( "JP2ECW" );
206 #endif
207 
208  // reload settings to take into account QCoreApplication and QgsApplication
209  // configuration
210  sSettings()->load();
211 
212  // init and configure logger
214  QgsServerLogger::instance()->setLogLevel( sSettings()->logLevel() );
215  if ( ! sSettings()->logFile().isEmpty() )
216  {
217  QgsServerLogger::instance()->setLogFile( sSettings()->logFile() );
218  }
219  else if ( sSettings()->logStderr() )
220  {
222  }
223 
224  // Logging handlers for CRS grid issues
226  const QgsCoordinateReferenceSystem & destinationCrs,
227  const QgsDatumTransform::GridDetails & grid )
228  {
229  QgsServerLogger::instance()->logMessage( QStringLiteral( "Cannot use project transform between %1 and %2 - missing grid %3" )
232  grid.shortName ),
233  QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
234  } );
235 
236 
238  const QgsCoordinateReferenceSystem & destinationCrs,
239  const QgsDatumTransform::TransformDetails & details )
240  {
241  QString gridMessage;
242  for ( const QgsDatumTransform::GridDetails &grid : details.grids )
243  {
244  if ( !grid.isAvailable )
245  {
246  gridMessage.append( QStringLiteral( "This transformation requires the grid file '%1', which is not available for use on the system.\n" ).arg( grid.shortName ) );
247  }
248  }
249  QgsServerLogger::instance()->logMessage( QStringLiteral( "Cannot use project transform between %1 and %2 - %3.\n%4" )
252  details.name,
253  gridMessage ),
254  QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
255  } );
256 
257 
259  const QgsCoordinateReferenceSystem & destinationCrs,
260  const QgsDatumTransform::TransformDetails & preferredOperation,
261  const QgsDatumTransform::TransformDetails & availableOperation )
262  {
263 
264  QString gridMessage;
265  for ( const QgsDatumTransform::GridDetails &grid : preferredOperation.grids )
266  {
267  if ( !grid.isAvailable )
268  {
269  gridMessage.append( QStringLiteral( "This transformation requires the grid file '%1', which is not available for use on the system.\n" ).arg( grid.shortName ) );
270  if ( !grid.url.isEmpty() )
271  {
272  if ( !grid.packageName.isEmpty() )
273  {
274  gridMessage.append( QStringLiteral( "This grid is part of the '%1' package, available for download from %2.\n" ).arg( grid.packageName, grid.url ) );
275  }
276  else
277  {
278  gridMessage.append( QStringLiteral( "This grid is available for download from %1.\n" ).arg( grid.url ) );
279  }
280  }
281  }
282  }
283 
284  QString accuracyMessage;
285  if ( availableOperation.accuracy >= 0 && preferredOperation.accuracy >= 0 )
286  accuracyMessage = QStringLiteral( "Current transform '%1' has an accuracy of %2 meters, while the preferred transformation '%3' has accuracy %4 meters.\n" ).arg( availableOperation.name )
287  .arg( availableOperation.accuracy ).arg( preferredOperation.name ).arg( preferredOperation.accuracy );
288  else if ( preferredOperation.accuracy >= 0 )
289  accuracyMessage = QStringLiteral( "Current transform '%1' has an unknown accuracy, while the preferred transformation '%2' has accuracy %3 meters.\n" )
290  .arg( availableOperation.name, preferredOperation.name )
291  .arg( preferredOperation.accuracy );
292 
293  const QString longMessage = QStringLiteral( "The preferred transform between '%1' and '%2' is not available for use on the system.\n" ).arg( sourceCrs.userFriendlyIdentifier(),
294  destinationCrs.userFriendlyIdentifier() )
295  + gridMessage + accuracyMessage;
296 
297  QgsServerLogger::instance()->logMessage( longMessage, QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
298 
299  } );
300 
302  {
303  const QString longMessage = QStringLiteral( "No transform is available between %1 and %2: %3" )
304  .arg( sourceCrs.userFriendlyIdentifier(), destinationCrs.userFriendlyIdentifier(), error );
305  QgsServerLogger::instance()->logMessage( longMessage, QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
306  } );
307 
308  // Configure locale
309  initLocale();
310 
311  QgsMessageLog::logMessage( QStringLiteral( "QGIS Server Starting : %1 (%2)" ).arg( _QGIS_VERSION, QGSVERSION ), "Server", Qgis::MessageLevel::Info );
312 
313  // log settings currently used
314  sSettings()->logSummary();
315 
316  setupNetworkAccessManager();
317  QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
318 
319  // Instantiate the plugin directory so that providers are loaded
321  QgsMessageLog::logMessage( "Prefix PATH: " + QgsApplication::prefixPath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
322  QgsMessageLog::logMessage( "Plugin PATH: " + QgsApplication::pluginPath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
323  QgsMessageLog::logMessage( "PkgData PATH: " + QgsApplication::pkgDataPath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
324  QgsMessageLog::logMessage( "User DB PATH: " + QgsApplication::qgisUserDatabaseFilePath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
325  QgsMessageLog::logMessage( "Auth DB PATH: " + QgsApplication::qgisAuthDatabaseFilePath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
326  QgsMessageLog::logMessage( "SVG PATHS: " + QgsApplication::svgPaths().join( QDir::listSeparator() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
327 
328  QgsApplication::createDatabase(); //init qgis.db (e.g. necessary for user crs)
329 
330  // Initialize the authentication system
331  // creates or uses qgis-auth.db in ~/.qgis3/ or directory defined by QGIS_AUTH_DB_DIR_PATH env variable
332  // set the master password as first line of file defined by QGIS_AUTH_PASSWORD_FILE env variable
333  // (QGIS_AUTH_PASSWORD_FILE variable removed from environment after accessing)
335 
336  QString defaultConfigFilePath;
337  const QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs/.qgz file in the server directory
338  if ( projectFileInfo.exists() )
339  {
340  defaultConfigFilePath = projectFileInfo.absoluteFilePath();
341  QgsMessageLog::logMessage( "Using default project file: " + defaultConfigFilePath, QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
342  }
343  else
344  {
345  const QFileInfo adminSLDFileInfo = defaultAdminSLD();
346  if ( adminSLDFileInfo.exists() )
347  {
348  defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath();
349  }
350  }
351  // Store the config file path
352  sConfigFilePath = new QString( defaultConfigFilePath );
353 
354  //create cache for capabilities XML
355  sCapabilitiesCache = new QgsCapabilitiesCache();
356 
357  QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Roman" ) << QStringLiteral( "Bold" ) );
358 
359  sServiceRegistry = new QgsServiceRegistry();
360 
361  sServerInterface = new QgsServerInterfaceImpl( sCapabilitiesCache, sServiceRegistry, sSettings() );
362 
363  // Load service module
364  const QString modulePath = QgsApplication::libexecPath() + "server";
365  // qDebug() << QStringLiteral( "Initializing server modules from: %1" ).arg( modulePath );
366  sServiceRegistry->init( modulePath, sServerInterface );
367 
368  // Initialize config cache
369  QgsConfigCache::initialize( sSettings );
370 
371  sInitialized = true;
372  QgsMessageLog::logMessage( QStringLiteral( "Server initialized" ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
373  return true;
374 }
375 
376 
377 
378 void QgsServer::putenv( const QString &var, const QString &val )
379 {
380  if ( val.isEmpty() )
381  {
382  qunsetenv( var.toUtf8().data() );
383  }
384  else
385  {
386  qputenv( var.toUtf8().data(), val.toUtf8() );
387  }
388  sSettings()->load( var );
389 }
390 
391 void QgsServer::handleRequest( QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project )
392 {
394  {
395 
396  const QgsScopedRuntimeProfile profiler { QStringLiteral( "handleRequest" ), QStringLiteral( "server" ) };
397 
398  qApp->processEvents();
399 
400  response.clear();
401 
402  // Pass the filters to the requestHandler, this is needed for the following reasons:
403  // Allow server request to call sendResponse plugin hook if enabled
404  QgsFilterResponseDecorator responseDecorator( sServerInterface->filters(), response );
405 
406  //Request handler
407  QgsRequestHandler requestHandler( request, response );
408 
409  try
410  {
411  // TODO: split parse input into plain parse and processing from specific services
412  requestHandler.parseInput();
413  }
414  catch ( QgsMapServiceException &e )
415  {
416  QgsMessageLog::logMessage( "Parse input exception: " + e.message(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
417  requestHandler.setServiceException( e );
418  }
419 
420  // Set the request handler into the interface for plugins to manipulate it
421  sServerInterface->setRequestHandler( &requestHandler );
422 
423  // Initialize configfilepath so that is is available
424  // before calling plugin methods
425  // Note that plugins may still change that value using
426  // setConfigFilePath() interface method
427  if ( ! project )
428  {
429  const QString configFilePath = configPath( *sConfigFilePath, request.serverParameters().map() );
430  sServerInterface->setConfigFilePath( configFilePath );
431  }
432  else
433  {
434  sServerInterface->setConfigFilePath( project->fileName() );
435  }
436 
437  // Call requestReady() method (if enabled)
438  // This may also throw exceptions if there are errors in python plugins code
439  try
440  {
441  responseDecorator.start();
442  }
443  catch ( QgsException &ex )
444  {
445  // Internal server error
446  response.sendError( 500, QStringLiteral( "Internal Server Error" ) );
447  QgsMessageLog::logMessage( ex.what(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
448  }
449 
450  // Plugins may have set exceptions
451  if ( !requestHandler.exceptionRaised() )
452  {
453  try
454  {
455  const QgsServerParameters params = request.serverParameters();
456  printRequestParameters( params.toMap(), logLevel );
457 
458  // Setup project (config file path)
459  if ( !project )
460  {
461  const QString configFilePath = configPath( *sConfigFilePath, params.map() );
462 
463  // load the project if needed and not empty
464  if ( ! configFilePath.isEmpty() )
465  {
466  // Note that QgsConfigCache::project( ... ) call QgsProject::setInstance(...)
467  project = mConfigCache->project( configFilePath, sServerInterface->serverSettings() );
468  }
469  }
470 
471  // Set the current project instance
472  QgsProject::setInstance( const_cast<QgsProject *>( project ) );
473 
474  if ( project )
475  {
476  sServerInterface->setConfigFilePath( project->fileName() );
477  }
478  else
479  {
480  sServerInterface->setConfigFilePath( QString() );
481  }
482 
483  // Note that at this point we still might not have set a valid project.
484  // There are APIs that work without a project (e.g. the landing page catalog API that
485  // lists the available projects metadata).
486 
487  // Dispatcher: if SERVICE is set, we assume a OWS service, if not, let's try an API
488  // TODO: QGIS 4 fix the OWS services and treat them as APIs
489  QgsServerApi *api = nullptr;
490 
491  if ( params.service().isEmpty() && ( api = sServiceRegistry->apiForRequest( request ) ) )
492  {
493  const QgsServerApiContext context { api->rootPath(), &request, &responseDecorator, project, sServerInterface };
494  api->executeRequest( context );
495  }
496  else
497  {
498  // Project is mandatory for OWS at this point
499  if ( ! project )
500  {
501  throw QgsServerException( QStringLiteral( "Project file error. For OWS services: please provide a SERVICE and a MAP parameter pointing to a valid QGIS project file" ) );
502  }
503 
504  if ( ! params.fileName().isEmpty() )
505  {
506  const QString value = QString( "attachment; filename=\"%1\"" ).arg( params.fileName() );
507  requestHandler.setResponseHeader( QStringLiteral( "Content-Disposition" ), value );
508  }
509 
510  // Lookup for service
511  QgsService *service = sServiceRegistry->getService( params.service(), params.version() );
512  if ( service )
513  {
514  service->executeRequest( request, responseDecorator, project );
515  }
516  else
517  {
518  throw QgsOgcServiceException( QStringLiteral( "Service configuration error" ),
519  QStringLiteral( "Service unknown or unsupported. Current supported services (case-sensitive): WMS WFS WCS WMTS SampleService, or use a WFS3 (OGC API Features) endpoint" ) );
520  }
521  }
522  }
523  catch ( QgsServerException &ex )
524  {
525  responseDecorator.write( ex );
526  QString format;
527  QgsMessageLog::logMessage( ex.formatResponse( format ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
528  }
529  catch ( QgsException &ex )
530  {
531  // Internal server error
532  response.sendError( 500, QStringLiteral( "Internal Server Error" ) );
533  QgsMessageLog::logMessage( ex.what(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
534  }
535  }
536 
537  // Terminate the response
538  // This may also throw exceptions if there are errors in python plugins code
539  try
540  {
541  responseDecorator.finish();
542  }
543  catch ( QgsException &ex )
544  {
545  // Internal server error
546  response.sendError( 500, QStringLiteral( "Internal Server Error" ) );
547  QgsMessageLog::logMessage( ex.what(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
548  }
549 
550  // We are done using requestHandler in plugins, make sure we don't access
551  // to a deleted request handler from Python bindings
552  sServerInterface->clearRequestHandler();
553  }
554 
555  if ( logLevel == Qgis::MessageLevel::Info )
556  {
557  QgsMessageLog::logMessage( "Request finished in " + QString::number( QgsApplication::profiler()->profileTime( QStringLiteral( "handleRequest" ), QStringLiteral( "server" ) ) * 1000.0 ) + " ms", QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
558  if ( sSettings->logProfile() )
559  {
560  std::function <void( const QModelIndex &, int )> profileFormatter;
561  profileFormatter = [ &profileFormatter ]( const QModelIndex & idx, int level )
562  {
563  QgsMessageLog::logMessage( QStringLiteral( "Profile: %1%2, %3 : %4 ms" )
564  .arg( level > 0 ? QString().fill( '-', level ) + ' ' : QString() )
565  .arg( QgsApplication::profiler()->data( idx, QgsRuntimeProfilerNode::Roles::Group ).toString() )
566  .arg( QgsApplication::profiler()->data( idx, QgsRuntimeProfilerNode::Roles::Name ).toString() )
567  .arg( QString::number( QgsApplication::profiler()->data( idx, QgsRuntimeProfilerNode::Roles::Elapsed ).toDouble() * 1000.0 ) ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
568 
569  for ( int subRow = 0; subRow < QgsApplication::profiler()->rowCount( idx ); subRow++ )
570  {
571  const auto subIdx { QgsApplication::profiler()->index( subRow, 0, idx ) };
572  profileFormatter( subIdx, level + 1 );
573  }
574 
575  };
576 
577  for ( int row = 0; row < QgsApplication::profiler()->rowCount( ); row++ )
578  {
579  const auto idx { QgsApplication::profiler()->index( row, 0 ) };
580  profileFormatter( idx, 0 );
581  }
582  }
583  }
584 
585 
586  // Clear the profiler server section after each request
587  QgsApplication::profiler()->clear( QStringLiteral( "server" ) );
588 
589 }
590 
591 
592 #ifdef HAVE_SERVER_PYTHON_PLUGINS
593 void QgsServer::initPython()
594 {
595  // Init plugins
596  if ( ! QgsServerPlugins::initPlugins( sServerInterface ) )
597  {
598  QgsMessageLog::logMessage( QStringLiteral( "No server python plugins are available" ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
599  }
600  else
601  {
602  QgsMessageLog::logMessage( QStringLiteral( "Server python plugins loaded" ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
603  }
604 }
605 #endif
606 
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:115
static void skipGdalDriver(const QString &driver)
Sets the GDAL_SKIP environment variable to include the specified driver and then calls GDALDriverMana...
static QString pluginPath()
Returns the path to the application plugin directory.
static bool createDatabase(QString *errorMessage=nullptr)
initialize qgis.db
static void init(QString profileFolder=QString())
This method initializes paths etc for QGIS.
static QString pkgDataPath()
Returns the common root path of all application data directories.
static QString libexecPath()
Returns the path with utility executables (help viewer, crssync, ...)
static QStringList svgPaths()
Returns the paths to svg directories.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
static const char * QGIS_APPLICATION_NAME
static const char * QGIS_ORGANIZATION_DOMAIN
static QString prefixPath()
Returns the path to the application prefix directory.
static const char * QGIS_ORGANIZATION_NAME
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static QString qgisAuthDatabaseFilePath()
Returns the path to the user authentication database file: qgis-auth.db.
static QString qgisUserDatabaseFilePath()
Returns the path to the user qgis.db file.
bool init(const QString &pluginPath=QString(), const QString &authDatabasePath=QString())
init initialize QCA, prioritize qca-ossl plugin and optionally set up the authentication database
A cache for capabilities xml documents (by configuration file path)
static QgsConfigCache * instance()
Returns the current instance.
static void initialize(QgsServerSettings *settings)
Initialize from settings.
const QgsProject * project(const QString &path, const QgsServerSettings *settings=nullptr)
If the project is not cached yet, then the project is read from the path.
This class represents a coordinate reference system (CRS).
@ ShortString
A heavily abbreviated string, for use when a compact representation is required.
QString userFriendlyIdentifier(IdentifierType type=MediumString) const
Returns a user friendly identifier for the CRS.
static void setCustomMissingRequiredGridHandler(const std::function< void(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QgsDatumTransform::GridDetails &grid)> &handler)
Sets a custom handler to use when a coordinate transform is created between sourceCrs and destination...
static void setCustomCoordinateOperationCreationErrorHandler(const std::function< void(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &error)> &handler)
Sets a custom handler to use when a coordinate transform was required between sourceCrs and destinati...
static void setCustomMissingPreferredGridHandler(const std::function< void(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QgsDatumTransform::TransformDetails &preferredOperation, const QgsDatumTransform::TransformDetails &availableOperation)> &handler)
Sets a custom handler to use when a coordinate transform is created between sourceCrs and destination...
static void setCustomMissingGridUsedByContextHandler(const std::function< void(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QgsDatumTransform::TransformDetails &desiredOperation)> &handler)
Sets a custom handler to use when a coordinate operation was specified for use between sourceCrs and ...
Defines a QGIS exception class.
Definition: qgsexception.h:35
QString what() const
Definition: qgsexception.h:48
Class defining decorator for calling filter's hooks.
void finish() override
Finish the response, ending the transaction.
void start() SIP_THROW(QgsServerException)
Call filters requestReady() method.
static bool loadStandardTestFonts(const QStringList &loadstyles)
Loads standard test fonts from filesystem or qrc resource.
Exception class for WMS service exceptions (for compatibility only).
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
network access manager for QGIS
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
Exception base class for service exceptions.
QString message() const
Returns the exception message.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:104
static void setInstance(QgsProject *project)
Set the current project singleton instance to project.
Definition: qgsproject.cpp:473
QString fileName
Definition: qgsproject.h:107
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
This class is an interface hiding the details of reading input and writing output from/to a wms reque...
bool exceptionRaised() const
Pointer to last raised exception.
void parseInput()
Parses the input and creates a request neutral Parameter/Value map.
void setServiceException(const QgsServerException &ex)
Allow plugins to return a QgsMapServiceException.
void setResponseHeader(const QString &name, const QString &value)
Sets an HTTP response header.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void clear(const QString &group="startup")
clear Clear all profile data.
Scoped object for logging of the runtime for a single operation or group of operations.
The QgsServerApiContext class encapsulates the resources for a particular client request: the request...
Server generic API endpoint abstract base class.
Definition: qgsserverapi.h:81
virtual void executeRequest(const QgsServerApiContext &context) const =0
Executes a request by passing the given context to the API handlers.
virtual const QString rootPath() const =0
Returns the root path for the API.
Exception base class for server exceptions.
virtual QByteArray formatResponse(QString &responseFormat) const
Formats the exception for sending to client.
Interfaces exposed by QGIS Server and made available to plugins.
QgsServerSettings * serverSettings() override
Returns the server settings.
void setRequestHandler(QgsRequestHandler *requestHandler) override
Set the request handler.
void clearRequestHandler() override
Clear the request handler.
QgsServerFiltersMap filters() override
Returns the list of current QgsServerFilter.
void setConfigFilePath(const QString &configFilePath) override
Set the configuration file path.
static QgsServerLogger * instance()
Gets the singleton instance.
Qgis::MessageLevel logLevel() const
Gets the current log level.
void setLogLevel(Qgis::MessageLevel level)
Set the current log level.
void setLogFile(const QString &filename=QString())
Set the current log file.
void setLogStderr()
Activates logging to stderr.
void logMessage(const QString &message, const QString &tag, Qgis::MessageLevel level) override
Log a message from the server context.
QgsServerParameters provides an interface to retrieve and manipulate global parameters received from ...
QMap< QString, QString > toMap() const
Returns all parameters in a map.
QString map() const
Returns MAP parameter as a string or an empty string if not defined.
QString service() const
Returns SERVICE parameter as a string or an empty string if not defined.
QString fileName() const
Returns FILE_NAME parameter as a string or an empty string if not defined.
virtual QString version() const
Returns VERSION parameter as a string or an empty string if not defined.
static bool initPlugins(QgsServerInterface *interface)
Initializes the Python plugins.
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
QgsServerParameters serverParameters() const
Returns parameters.
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
virtual void clear()=0
Reset all headers and content for this response.
virtual void sendError(int code, const QString &message)=0
Send error This method delegates error handling at the server level.
Provides a way to retrieve settings by prioritizing according to environment variables,...
QgsServer()
Creates the server instance.
Definition: qgsserver.cpp:69
void handleRequest(QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project=nullptr)
Handles the request.
Definition: qgsserver.cpp:391
void putenv(const QString &var, const QString &val)
Set environment variable.
Definition: qgsserver.cpp:378
QgsServiceRegistry Class defining the registry manager for QGIS server services.
QgsServerApi * apiForRequest(const QgsServerRequest &request) const
Searches the API register for an API matching the request and returns a (possibly NULL) pointer to it...
QgsService * getService(const QString &name, const QString &version=QString())
Retrieve a service from its name.
QgsService Class defining interfaces for QGIS server services.
Definition: qgsservice.h:40
virtual void executeRequest(const QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project)=0
Execute the requests and set result in QgsServerRequest.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Q_GLOBAL_STATIC(QgsServerSettings, sSettings)
Contains information about a projection transformation grid file.
QString shortName
Short name of transform grid.
Contains information about a coordinate transformation operation.
double accuracy
Transformation accuracy (in meters)
QString name
Display name of transform operation.
QList< QgsDatumTransform::GridDetails > grids
Contains a list of transform grids used by the operation.