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