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