QGIS API Documentation  3.21.0-Master (5b68dc587e)
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 "qgsserver.h"
24 #include "qgsauthmanager.h"
25 #include "qgscapabilitiescache.h"
26 #include "qgsfontutils.h"
27 #include "qgsrequesthandler.h"
28 #include "qgsproject.h"
29 #include "qgsproviderregistry.h"
30 #include "qgslogger.h"
31 #include "qgsmapserviceexception.h"
33 #include "qgsserverlogger.h"
34 #include "qgsserverrequest.h"
36 #include "qgsservice.h"
37 #include "qgsserverapi.h"
38 #include "qgsserverapicontext.h"
39 #include "qgsserverparameters.h"
40 #include "qgsapplication.h"
41 #include "qgsruntimeprofiler.h"
42 #include "qgscoordinatetransform.h"
43 
44 #include <QDomDocument>
45 #include <QNetworkDiskCache>
46 #include <QSettings>
47 #include <QElapsedTimer>
48 
49 // TODO: remove, it's only needed by a single debug message
50 #include <fcgi_stdio.h>
51 #include <cstdlib>
52 
53 
54 // Server status static initializers.
55 // Default values are for C++, SIP bindings will override their
56 // options in in init()
57 
58 QString *QgsServer::sConfigFilePath = nullptr;
59 QgsCapabilitiesCache *QgsServer::sCapabilitiesCache = nullptr;
60 QgsServerInterfaceImpl *QgsServer::sServerInterface = nullptr;
61 // Initialization must run once for all servers
62 bool QgsServer::sInitialized = false;
63 
64 QgsServiceRegistry *QgsServer::sServiceRegistry = nullptr;
65 
67 
69 {
70  // QgsApplication must exist
71  if ( qobject_cast<QgsApplication *>( qApp ) == nullptr )
72  {
73  qFatal( "A QgsApplication must exist before a QgsServer instance can be created." );
74  abort();
75  }
76  init();
77  mConfigCache = QgsConfigCache::instance();
78 }
79 
80 QFileInfo QgsServer::defaultAdminSLD()
81 {
82  return QFileInfo( QStringLiteral( "admin.sld" ) );
83 }
84 
85 void QgsServer::setupNetworkAccessManager()
86 {
87  const QSettings settings;
89  QNetworkDiskCache *cache = new QNetworkDiskCache( nullptr );
90  const qint64 cacheSize = sSettings()->cacheSize();
91  const QString cacheDirectory = sSettings()->cacheDirectory();
92  cache->setCacheDirectory( cacheDirectory );
93  cache->setMaximumCacheSize( cacheSize );
94  QgsMessageLog::logMessage( QStringLiteral( "cacheDirectory: %1" ).arg( cache->cacheDirectory() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
95  QgsMessageLog::logMessage( QStringLiteral( "maximumCacheSize: %1" ).arg( cache->maximumCacheSize() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
96  nam->setCache( cache );
97 }
98 
99 QFileInfo QgsServer::defaultProjectFile()
100 {
101  const QDir currentDir;
102  fprintf( FCGI_stderr, "current directory: %s\n", currentDir.absolutePath().toUtf8().constData() );
103  QStringList nameFilterList;
104  nameFilterList << QStringLiteral( "*.qgs" )
105  << QStringLiteral( "*.qgz" );
106  const QFileInfoList projectFiles = currentDir.entryInfoList( nameFilterList, QDir::Files, QDir::Name );
107  for ( int x = 0; x < projectFiles.size(); x++ )
108  {
109  QgsMessageLog::logMessage( projectFiles.at( x ).absoluteFilePath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
110  }
111  if ( projectFiles.isEmpty() )
112  {
113  return QFileInfo();
114  }
115  return projectFiles.at( 0 );
116 }
117 
118 void QgsServer::printRequestParameters( const QMap< QString, QString> &parameterMap, Qgis::MessageLevel logLevel )
119 {
120  if ( logLevel > Qgis::MessageLevel::Info )
121  {
122  return;
123  }
124 
125  QMap< QString, QString>::const_iterator pIt = parameterMap.constBegin();
126  for ( ; pIt != parameterMap.constEnd(); ++pIt )
127  {
128  QgsMessageLog::logMessage( pIt.key() + ":" + pIt.value(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
129  }
130 }
131 
132 QString QgsServer::configPath( const QString &defaultConfigPath, const QString &configPath )
133 {
134  QString cfPath( defaultConfigPath );
135  const QString projectFile = sSettings()->projectFile();
136  if ( !projectFile.isEmpty() )
137  {
138  cfPath = projectFile;
139  QgsDebugMsg( QStringLiteral( "QGIS_PROJECT_FILE:%1" ).arg( cfPath ) );
140  }
141  else
142  {
143  if ( configPath.isEmpty() )
144  {
145  // Read it from the environment, because a rewrite rule may have rewritten it
146  if ( getenv( "QGIS_PROJECT_FILE" ) )
147  {
148  cfPath = getenv( "QGIS_PROJECT_FILE" );
149  QgsMessageLog::logMessage( QStringLiteral( "Using configuration file path from environment: %1" ).arg( cfPath ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
150  }
151  else if ( ! defaultConfigPath.isEmpty() )
152  {
153  QgsMessageLog::logMessage( QStringLiteral( "Using default configuration file path: %1" ).arg( defaultConfigPath ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
154  }
155  }
156  else
157  {
158  cfPath = configPath;
159  QgsDebugMsg( QStringLiteral( "MAP:%1" ).arg( cfPath ) );
160  }
161  }
162  return cfPath;
163 }
164 
165 void QgsServer::initLocale()
166 {
167  // System locale override
168  if ( ! sSettings()->overrideSystemLocale().isEmpty() )
169  {
170  QLocale::setDefault( QLocale( sSettings()->overrideSystemLocale() ) );
171  }
172  // Number group separator settings
173  QLocale currentLocale;
174  if ( sSettings()->showGroupSeparator() )
175  {
176  currentLocale.setNumberOptions( currentLocale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
177  }
178  else
179  {
180  currentLocale.setNumberOptions( currentLocale.numberOptions() |= QLocale::NumberOption::OmitGroupSeparator );
181  }
182  QLocale::setDefault( currentLocale );
183 }
184 
185 bool QgsServer::init()
186 {
187  if ( sInitialized )
188  {
189  return false;
190  }
191 
192  QCoreApplication::setOrganizationName( QgsApplication::QGIS_ORGANIZATION_NAME );
193  QCoreApplication::setOrganizationDomain( QgsApplication::QGIS_ORGANIZATION_DOMAIN );
194  QCoreApplication::setApplicationName( QgsApplication::QGIS_APPLICATION_NAME );
195 
196  // TODO: remove QGIS_OPTIONS_PATH from settings and rely on QgsApplication's env var QGIS_CUSTOM_CONFIG_PATH
197  // Note that QGIS_CUSTOM_CONFIG_PATH gives /tmp/qt_temp-rUpsId/profiles/default/QGIS/QGIS3.ini
198  // while QGIS_OPTIONS_PATH gives /tmp/qt_temp-rUpsId/QGIS/QGIS3.ini
199  QgsApplication::init( qgetenv( "QGIS_OPTIONS_PATH" ) );
200 
201 #if defined(SERVER_SKIP_ECW)
202  QgsMessageLog::logMessage( "Skipping GDAL ECW drivers in server.", "Server", Qgis::MessageLevel::Info );
204  QgsApplication::skipGdalDriver( "JP2ECW" );
205 #endif
206 
207  // reload settings to take into account QCoreApplication and QgsApplication
208  // configuration
209  sSettings()->load();
210 
211  // init and configure logger
213  QgsServerLogger::instance()->setLogLevel( sSettings()->logLevel() );
214  if ( ! sSettings()->logFile().isEmpty() )
215  {
216  QgsServerLogger::instance()->setLogFile( sSettings()->logFile() );
217  }
218  else if ( sSettings()->logStderr() )
219  {
221  }
222 
223  // Logging handlers for CRS grid issues
225  const QgsCoordinateReferenceSystem & destinationCrs,
226  const QgsDatumTransform::GridDetails & grid )
227  {
228  QgsServerLogger::instance()->logMessage( QStringLiteral( "Cannot use project transform between %1 and %2 - missing grid %3" )
231  grid.shortName ),
232  QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
233  } );
234 
235 
237  const QgsCoordinateReferenceSystem & destinationCrs,
238  const QgsDatumTransform::TransformDetails & details )
239  {
240  QString gridMessage;
241  for ( const QgsDatumTransform::GridDetails &grid : details.grids )
242  {
243  if ( !grid.isAvailable )
244  {
245  gridMessage.append( QStringLiteral( "This transformation requires the grid file '%1', which is not available for use on the system.\n" ).arg( grid.shortName ) );
246  }
247  }
248  QgsServerLogger::instance()->logMessage( QStringLiteral( "Cannot use project transform between %1 and %2 - %3.\n%4" )
251  details.name,
252  gridMessage ),
253  QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
254  } );
255 
256 
258  const QgsCoordinateReferenceSystem & destinationCrs,
259  const QgsDatumTransform::TransformDetails & preferredOperation,
260  const QgsDatumTransform::TransformDetails & availableOperation )
261  {
262 
263  QString gridMessage;
264  for ( const QgsDatumTransform::GridDetails &grid : preferredOperation.grids )
265  {
266  if ( !grid.isAvailable )
267  {
268  gridMessage.append( QStringLiteral( "This transformation requires the grid file '%1', which is not available for use on the system.\n" ).arg( grid.shortName ) );
269  if ( !grid.url.isEmpty() )
270  {
271  if ( !grid.packageName.isEmpty() )
272  {
273  gridMessage.append( QStringLiteral( "This grid is part of the '%1' package, available for download from %2.\n" ).arg( grid.packageName, grid.url ) );
274  }
275  else
276  {
277  gridMessage.append( QStringLiteral( "This grid is available for download from %1.\n" ).arg( grid.url ) );
278  }
279  }
280  }
281  }
282 
283  QString accuracyMessage;
284  if ( availableOperation.accuracy >= 0 && preferredOperation.accuracy >= 0 )
285  accuracyMessage = QStringLiteral( "Current transform '%1' has an accuracy of %2 meters, while the preferred transformation '%3' has accuracy %4 meters.\n" ).arg( availableOperation.name )
286  .arg( availableOperation.accuracy ).arg( preferredOperation.name ).arg( preferredOperation.accuracy );
287  else if ( preferredOperation.accuracy >= 0 )
288  accuracyMessage = QStringLiteral( "Current transform '%1' has an unknown accuracy, while the preferred transformation '%2' has accuracy %3 meters.\n" )
289  .arg( availableOperation.name, preferredOperation.name )
290  .arg( preferredOperation.accuracy );
291 
292  const QString longMessage = QStringLiteral( "The preferred transform between '%1' and '%2' is not available for use on the system.\n" ).arg( sourceCrs.userFriendlyIdentifier(),
293  destinationCrs.userFriendlyIdentifier() )
294  + gridMessage + accuracyMessage;
295 
296  QgsServerLogger::instance()->logMessage( longMessage, QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
297 
298  } );
299 
301  {
302  const QString longMessage = QStringLiteral( "No transform is available between %1 and %2: %3" )
303  .arg( sourceCrs.userFriendlyIdentifier(), destinationCrs.userFriendlyIdentifier(), error );
304  QgsServerLogger::instance()->logMessage( longMessage, QStringLiteral( "QGIS Server" ), Qgis::MessageLevel::Warning );
305  } );
306 
307  // Configure locale
308  initLocale();
309 
310  // log settings currently used
311  sSettings()->logSummary();
312 
313  setupNetworkAccessManager();
314  QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
315 
316  // Instantiate the plugin directory so that providers are loaded
318  QgsMessageLog::logMessage( "Prefix PATH: " + QgsApplication::prefixPath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
319  QgsMessageLog::logMessage( "Plugin PATH: " + QgsApplication::pluginPath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
320  QgsMessageLog::logMessage( "PkgData PATH: " + QgsApplication::pkgDataPath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
321  QgsMessageLog::logMessage( "User DB PATH: " + QgsApplication::qgisUserDatabaseFilePath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
322  QgsMessageLog::logMessage( "Auth DB PATH: " + QgsApplication::qgisAuthDatabaseFilePath(), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
323  QgsMessageLog::logMessage( "SVG PATHS: " + QgsApplication::svgPaths().join( QDir::listSeparator() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
324 
325  QgsApplication::createDatabase(); //init qgis.db (e.g. necessary for user crs)
326 
327  // Initialize the authentication system
328  // creates or uses qgis-auth.db in ~/.qgis3/ or directory defined by QGIS_AUTH_DB_DIR_PATH env variable
329  // set the master password as first line of file defined by QGIS_AUTH_PASSWORD_FILE env variable
330  // (QGIS_AUTH_PASSWORD_FILE variable removed from environment after accessing)
332 
333  QString defaultConfigFilePath;
334  const QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs/.qgz file in the server directory
335  if ( projectFileInfo.exists() )
336  {
337  defaultConfigFilePath = projectFileInfo.absoluteFilePath();
338  QgsMessageLog::logMessage( "Using default project file: " + defaultConfigFilePath, QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
339  }
340  else
341  {
342  const QFileInfo adminSLDFileInfo = defaultAdminSLD();
343  if ( adminSLDFileInfo.exists() )
344  {
345  defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath();
346  }
347  }
348  // Store the config file path
349  sConfigFilePath = new QString( defaultConfigFilePath );
350 
351  //create cache for capabilities XML
352  sCapabilitiesCache = new QgsCapabilitiesCache();
353 
354  QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Roman" ) << QStringLiteral( "Bold" ) );
355 
356  sServiceRegistry = new QgsServiceRegistry();
357 
358  sServerInterface = new QgsServerInterfaceImpl( sCapabilitiesCache, sServiceRegistry, sSettings() );
359 
360  // Load service module
361  const QString modulePath = QgsApplication::libexecPath() + "server";
362  // qDebug() << QStringLiteral( "Initializing server modules from: %1" ).arg( modulePath );
363  sServiceRegistry->init( modulePath, sServerInterface );
364 
365  sInitialized = true;
366  QgsMessageLog::logMessage( QStringLiteral( "Server initialized" ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
367  return true;
368 }
369 
370 
371 
372 void QgsServer::putenv( const QString &var, const QString &val )
373 {
374  if ( val.isEmpty() )
375  {
376  qunsetenv( var.toUtf8().data() );
377  }
378  else
379  {
380  qputenv( var.toUtf8().data(), val.toUtf8() );
381  }
382  sSettings()->load( var );
383 }
384 
385 void QgsServer::handleRequest( QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project )
386 {
388  {
389 
390  const QgsScopedRuntimeProfile profiler { QStringLiteral( "handleRequest" ), QStringLiteral( "server" ) };
391 
392  qApp->processEvents();
393 
394  response.clear();
395 
396  // Pass the filters to the requestHandler, this is needed for the following reasons:
397  // Allow server request to call sendResponse plugin hook if enabled
398  QgsFilterResponseDecorator responseDecorator( sServerInterface->filters(), response );
399 
400  //Request handler
401  QgsRequestHandler requestHandler( request, response );
402 
403  try
404  {
405  // TODO: split parse input into plain parse and processing from specific services
406  requestHandler.parseInput();
407  }
408  catch ( QgsMapServiceException &e )
409  {
410  QgsMessageLog::logMessage( "Parse input exception: " + e.message(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
411  requestHandler.setServiceException( e );
412  }
413 
414  // Set the request handler into the interface for plugins to manipulate it
415  sServerInterface->setRequestHandler( &requestHandler );
416 
417  // Initialize configfilepath so that is is available
418  // before calling plugin methods
419  // Note that plugins may still change that value using
420  // setConfigFilePath() interface method
421  if ( ! project )
422  {
423  const QString configFilePath = configPath( *sConfigFilePath, request.serverParameters().map() );
424  sServerInterface->setConfigFilePath( configFilePath );
425  }
426  else
427  {
428  sServerInterface->setConfigFilePath( project->fileName() );
429  }
430 
431  // Call requestReady() method (if enabled)
432  // This may also throw exceptions if there are errors in python plugins code
433  try
434  {
435  responseDecorator.start();
436  }
437  catch ( QgsException &ex )
438  {
439  // Internal server error
440  response.sendError( 500, QStringLiteral( "Internal Server Error" ) );
441  QgsMessageLog::logMessage( ex.what(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
442  }
443 
444  // Plugins may have set exceptions
445  if ( !requestHandler.exceptionRaised() )
446  {
447  try
448  {
449  const QgsServerParameters params = request.serverParameters();
450  printRequestParameters( params.toMap(), logLevel );
451 
452  // Setup project (config file path)
453  if ( ! project )
454  {
455  const QString configFilePath = configPath( *sConfigFilePath, params.map() );
456 
457  // load the project if needed and not empty
458  if ( ! configFilePath.isEmpty() )
459  {
460  project = mConfigCache->project( configFilePath, sServerInterface->serverSettings() );
461  }
462  }
463 
464  // Set the current project instance
465  QgsProject::setInstance( const_cast<QgsProject *>( project ) );
466 
467  if ( project )
468  {
469  sServerInterface->setConfigFilePath( project->fileName() );
470  }
471  else
472  {
473  sServerInterface->setConfigFilePath( QString() );
474  }
475 
476  // Note that at this point we still might not have set a valid project.
477  // There are APIs that work without a project (e.g. the landing page catalog API that
478  // lists the available projects metadata).
479 
480  // Dispatcher: if SERVICE is set, we assume a OWS service, if not, let's try an API
481  // TODO: QGIS 4 fix the OWS services and treat them as APIs
482  QgsServerApi *api = nullptr;
483  if ( params.service().isEmpty() && ( api = sServiceRegistry->apiForRequest( request ) ) )
484  {
485  const QgsServerApiContext context { api->rootPath(), &request, &responseDecorator, project, sServerInterface };
486  api->executeRequest( context );
487  }
488  else
489  {
490 
491  // Project is mandatory for OWS at this point
492  if ( ! project )
493  {
494  throw QgsServerException( QStringLiteral( "Project file error. For OWS services: please provide a SERVICE and a MAP parameter pointing to a valid QGIS project file" ) );
495  }
496 
497  if ( ! params.fileName().isEmpty() )
498  {
499  const QString value = QString( "attachment; filename=\"%1\"" ).arg( params.fileName() );
500  requestHandler.setResponseHeader( QStringLiteral( "Content-Disposition" ), value );
501  }
502 
503  // Lookup for service
504  QgsService *service = sServiceRegistry->getService( params.service(), params.version() );
505  if ( service )
506  {
507  service->executeRequest( request, responseDecorator, project );
508  }
509  else
510  {
511  throw QgsOgcServiceException( QStringLiteral( "Service configuration error" ),
512  QStringLiteral( "Service unknown or unsupported. Current supported services (case-sensitive): WMS WFS WCS WMTS SampleService, or use a WFS3 (OGC API Features) endpoint" ) );
513  }
514  }
515  }
516  catch ( QgsServerException &ex )
517  {
518  responseDecorator.write( ex );
519  QString format;
520  QgsMessageLog::logMessage( ex.formatResponse( format ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
521  }
522  catch ( QgsException &ex )
523  {
524  // Internal server error
525  response.sendError( 500, QStringLiteral( "Internal Server Error" ) );
526  QgsMessageLog::logMessage( ex.what(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
527  }
528  }
529 
530  // Terminate the response
531  // This may also throw exceptions if there are errors in python plugins code
532  try
533  {
534  responseDecorator.finish();
535  }
536  catch ( QgsException &ex )
537  {
538  // Internal server error
539  response.sendError( 500, QStringLiteral( "Internal Server Error" ) );
540  QgsMessageLog::logMessage( ex.what(), QStringLiteral( "Server" ), Qgis::MessageLevel::Critical );
541  }
542 
543  // We are done using requestHandler in plugins, make sure we don't access
544  // to a deleted request handler from Python bindings
545  sServerInterface->clearRequestHandler();
546  }
547 
548  if ( logLevel == Qgis::MessageLevel::Info )
549  {
550  QgsMessageLog::logMessage( "Request finished in " + QString::number( QgsApplication::profiler()->profileTime( QStringLiteral( "handleRequest" ), QStringLiteral( "server" ) ) * 1000.0 ) + " ms", QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
551  if ( sSettings->logProfile() )
552  {
553  std::function <void( const QModelIndex &, int )> profileFormatter;
554  profileFormatter = [ &profileFormatter ]( const QModelIndex & idx, int level )
555  {
556  QgsMessageLog::logMessage( QStringLiteral( "Profile: %1%2, %3 : %4 ms" )
557  .arg( level > 0 ? QString().fill( '-', level ) + ' ' : QString() )
558  .arg( QgsApplication::profiler()->data( idx, QgsRuntimeProfilerNode::Roles::Group ).toString() )
559  .arg( QgsApplication::profiler()->data( idx, QgsRuntimeProfilerNode::Roles::Name ).toString() )
560  .arg( QString::number( QgsApplication::profiler()->data( idx, QgsRuntimeProfilerNode::Roles::Elapsed ).toDouble() * 1000.0 ) ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
561 
562  for ( int subRow = 0; subRow < QgsApplication::profiler()->rowCount( idx ); subRow++ )
563  {
564  const auto subIdx { QgsApplication::profiler()->index( subRow, 0, idx ) };
565  profileFormatter( subIdx, level + 1 );
566  }
567 
568  };
569 
570  for ( int row = 0; row < QgsApplication::profiler()->rowCount( ); row++ )
571  {
572  const auto idx { QgsApplication::profiler()->index( row, 0 ) };
573  profileFormatter( idx, 0 );
574  }
575  }
576  }
577 
578 
579  // Clear the profiler server section after each request
580  QgsApplication::profiler()->clear( QStringLiteral( "server" ) );
581 
582 }
583 
584 
585 #ifdef HAVE_SERVER_PYTHON_PLUGINS
586 void QgsServer::initPython()
587 {
588  // Init plugins
589  if ( ! QgsServerPlugins::initPlugins( sServerInterface ) )
590  {
591  QgsMessageLog::logMessage( QStringLiteral( "No server python plugins are available" ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
592  }
593  else
594  {
595  QgsMessageLog::logMessage( QStringLiteral( "Server python plugins loaded" ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
596  }
597 }
598 #endif
599 
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:106
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.
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:101
static void setInstance(QgsProject *project)
Set the current project singleton instance to project.
Definition: qgsproject.cpp:461
QString fileName
Definition: qgsproject.h:104
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:68
void handleRequest(QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project=nullptr)
Handles the request.
Definition: qgsserver.cpp:385
void putenv(const QString &var, const QString &val)
Set environment variable.
Definition: qgsserver.cpp:372
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.