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