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