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