QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsserversettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsserversettings.cpp
3  ---------------------
4  begin : December 19, 2016
5  copyright : (C) 2016 by Paul Blottiere
6  email : paul dot blottiere at oslandia dot com
7 
8 ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "qgsserversettings.h"
20 #include "qgsapplication.h"
21 
22 #include <QSettings>
23 #include <QDir>
24 
26 {
27  load();
28 }
29 
30 void QgsServerSettings::initSettings()
31 {
32  mSettings.clear();
33 
34  // options path
35  const Setting sOptPath = { QgsServerSettingsEnv::QGIS_OPTIONS_PATH,
37  QStringLiteral( "Override the default path for user configuration" ),
38  QString(),
39  QVariant::String,
40  QVariant( "" ),
41  QVariant()
42  };
43  mSettings[ sOptPath.envVar ] = sOptPath;
44 
45  // parallel rendering
48  QStringLiteral( "Activate/Deactivate parallel rendering for WMS getMap request" ),
49  QStringLiteral( "/qgis/parallel_rendering" ),
50  QVariant::Bool,
51  QVariant( false ),
52  QVariant()
53  };
54  mSettings[ sParRend.envVar ] = sParRend;
55 
56  // max threads
57  const Setting sMaxThreads = { QgsServerSettingsEnv::QGIS_SERVER_MAX_THREADS,
59  QStringLiteral( "Number of threads to use when parallel rendering is activated" ),
60  QStringLiteral( "/qgis/max_threads" ),
61  QVariant::Int,
62  QVariant( -1 ),
63  QVariant()
64  };
65  mSettings[ sMaxThreads.envVar ] = sMaxThreads;
66 
67  // log level
68  const Setting sLogLevel = { QgsServerSettingsEnv::QGIS_SERVER_LOG_LEVEL,
70  QStringLiteral( "Log level" ),
71  QString(),
72  QVariant::Int,
73  QVariant( Qgis::None ),
74  QVariant()
75  };
76  mSettings[ sLogLevel.envVar ] = sLogLevel;
77 
78  // log file
79  const Setting sLogFile = { QgsServerSettingsEnv::QGIS_SERVER_LOG_FILE,
81  QStringLiteral( "Log file" ),
82  QString(),
83  QVariant::String,
84  QVariant( "" ),
85  QVariant()
86  };
87  mSettings[ sLogFile.envVar ] = sLogFile;
88 
89  // log to stderr
90  const Setting sLogStderr = { QgsServerSettingsEnv::QGIS_SERVER_LOG_STDERR,
92  QStringLiteral( "Activate/Deactivate logging to stderr" ),
93  QString(),
94  QVariant::Bool,
95  QVariant( false ),
96  QVariant()
97  };
98  mSettings[ sLogStderr.envVar ] = sLogStderr;
99 
100  // project file
101  const Setting sProject = { QgsServerSettingsEnv::QGIS_PROJECT_FILE,
103  QStringLiteral( "QGIS project file" ),
104  QString(),
105  QVariant::String,
106  QVariant( "" ),
107  QVariant()
108  };
109  mSettings[ sProject.envVar ] = sProject;
110 
111  // cache directory
112  const Setting sCacheDir = { QgsServerSettingsEnv::QGIS_SERVER_CACHE_DIRECTORY,
114  QStringLiteral( "Specify the cache directory" ),
115  QStringLiteral( "/cache/directory" ),
116  QVariant::String,
117  QVariant( QgsApplication::qgisSettingsDirPath() + "cache" ),
118  QVariant()
119  };
120  mSettings[ sCacheDir.envVar ] = sCacheDir;
121 
122  // cache size
123  const Setting sCacheSize = { QgsServerSettingsEnv::QGIS_SERVER_CACHE_SIZE,
125  QStringLiteral( "Specify the cache size" ),
126  QStringLiteral( "/cache/size" ),
127  QVariant::LongLong,
128  QVariant( 50 * 1024 * 1024 ),
129  QVariant()
130  };
131  mSettings[ sCacheSize.envVar ] = sCacheSize;
132 
133  // system locale override
134  const Setting sOverrideSystemLocale = { QgsServerSettingsEnv::QGIS_SERVER_OVERRIDE_SYSTEM_LOCALE,
136  QStringLiteral( "Override system locale" ),
137  QStringLiteral( "/locale/userLocale" ),
138  QVariant::String,
139  QVariant( "" ),
140  QVariant()
141  };
142  mSettings[ sOverrideSystemLocale.envVar ] = sOverrideSystemLocale;
143 
144  // bad layers handling
145  const Setting sIgnoreBadLayers = { QgsServerSettingsEnv::QGIS_SERVER_IGNORE_BAD_LAYERS,
147  QStringLiteral( "Ignore bad layers" ),
148  QString(),
149  QVariant::Bool,
150  QVariant( false ),
151  QVariant()
152  };
153  mSettings[ sIgnoreBadLayers.envVar ] = sIgnoreBadLayers;
154 
155  // trust layer metadata
156  const Setting sTrustLayerMetadata = { QgsServerSettingsEnv::QGIS_SERVER_TRUST_LAYER_METADATA,
158  QStringLiteral( "Trust layer metadata" ),
159  QString(),
160  QVariant::Bool,
161  QVariant( false ),
162  QVariant()
163  };
164  mSettings[ sTrustLayerMetadata.envVar ] = sTrustLayerMetadata;
165 
166  // don't load layouts
167  const Setting sDontLoadLayouts = { QgsServerSettingsEnv::QGIS_SERVER_DISABLE_GETPRINT,
169  QStringLiteral( "Don't load layouts" ),
170  QString(),
171  QVariant::Bool,
172  QVariant( false ),
173  QVariant()
174  };
175  mSettings[ sDontLoadLayouts.envVar ] = sDontLoadLayouts;
176 
177  // show group separator
178  const Setting sShowGroupSeparator = { QgsServerSettingsEnv::QGIS_SERVER_SHOW_GROUP_SEPARATOR,
180  QStringLiteral( "Show group (thousands) separator" ),
181  QStringLiteral( "/locale/showGroupSeparator" ),
182  QVariant::String,
183  QVariant( false ),
184  QVariant()
185  };
186  mSettings[ sShowGroupSeparator.envVar ] = sShowGroupSeparator;
187 
188  // max height
189  const Setting sMaxHeight = { QgsServerSettingsEnv::QGIS_SERVER_WMS_MAX_HEIGHT,
191  QStringLiteral( "Maximum height for a WMS request. The lower one of this and the project configuration is used." ),
192  QStringLiteral( "/qgis/max_wms_height" ),
193  QVariant::LongLong,
194  QVariant( -1 ),
195  QVariant()
196  };
197  mSettings[ sMaxHeight.envVar ] = sMaxHeight;
198 
199  // max width
200  const Setting sMaxWidth = { QgsServerSettingsEnv::QGIS_SERVER_WMS_MAX_WIDTH,
202  QStringLiteral( "Maximum width for a WMS request. The most conservative between this and the project one is used" ),
203  QStringLiteral( "/qgis/max_wms_width" ),
204  QVariant::LongLong,
205  QVariant( -1 ),
206  QVariant()
207  };
208  mSettings[ sMaxWidth.envVar ] = sMaxWidth;
209 
210  // API templates and static override directory
211  const Setting sApiResourcesDirectory = { QgsServerSettingsEnv::QGIS_SERVER_API_RESOURCES_DIRECTORY,
213  QStringLiteral( "Base directory where HTML templates and static assets (e.g. images, js and css files) are searched for" ),
214  QStringLiteral( "/qgis/server_api_resources_directory" ),
215  QVariant::String,
216  QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( QStringLiteral( "resources/server/api" ) ),
217  QString()
218  };
219 
220  mSettings[ sApiResourcesDirectory.envVar ] = sApiResourcesDirectory;
221 
222  // API WFS3 max limit
223  const Setting sApiWfs3MaxLimit = { QgsServerSettingsEnv::QGIS_SERVER_API_WFS3_MAX_LIMIT,
225  QStringLiteral( "Maximum value for \"limit\" in a features request, defaults to 10000" ),
226  QStringLiteral( "/qgis/server_api_wfs3_max_limit" ),
227  QVariant::LongLong,
228  QVariant( 10000 ),
229  QVariant()
230  };
231 
232  mSettings[ sApiWfs3MaxLimit.envVar ] = sApiWfs3MaxLimit;
233 
234  // projects directory for landing page service
235  const Setting sProjectsDirectories = { QgsServerSettingsEnv::QGIS_SERVER_LANDING_PAGE_PROJECTS_DIRECTORIES,
237  QStringLiteral( "Directories used by the landing page service to find .qgs and .qgz projects" ),
238  QStringLiteral( "/qgis/server_projects_directories" ),
239  QVariant::String,
240  QVariant( "" ),
241  QVariant()
242  };
243 
244  mSettings[ sProjectsDirectories.envVar ] = sProjectsDirectories;
245 
246  // postgresql connection string for landing page service
247  const Setting sProjectsPgConnections = { QgsServerSettingsEnv::QGIS_SERVER_LANDING_PAGE_PROJECTS_PG_CONNECTIONS,
249  QStringLiteral( "PostgreSQL connection strings used by the landing page service to find projects" ),
250  QStringLiteral( "/qgis/server_projects_pg_connections" ),
251  QVariant::String,
252  QVariant( "" ),
253  QVariant()
254  };
255 
256  mSettings[ sProjectsPgConnections.envVar ] = sProjectsPgConnections;
257 
258  // log profile
259  const Setting sLogProfile = { QgsServerSettingsEnv::QGIS_SERVER_LOG_PROFILE,
261  QStringLiteral( "Add detailed profile information to the logs, only effective when QGIS_SERVER_LOG_LEVEL=0" ),
262  QStringLiteral( "/qgis/server_log_profile" ),
263  QVariant::Bool,
264  QVariant( false ),
265  QVariant()
266  };
267 
268  mSettings[ sLogProfile.envVar ] = sLogProfile;
269 
270 }
271 
273 {
274  // init settings each time to take into account QgsApplication and
275  // QCoreApplication configuration for some default values
276  initSettings();
277 
278  // store environment variables
279  QMap<QgsServerSettingsEnv::EnvVar, QString> env = getEnv();
280 
281  // load QSettings if QGIS_OPTIONS_PATH is defined
282  loadQSettings( env[ QgsServerSettingsEnv::QGIS_OPTIONS_PATH ] );
283 
284  // prioritize values: 'env var' -> 'ini file' -> 'default value'
285  prioritize( env );
286 }
287 
288 bool QgsServerSettings::load( const QString &envVarName )
289 {
290  bool rc( false );
291  const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerSettingsEnv::EnvVar>() );
292  const int value = metaEnum.keyToValue( envVarName.toStdString().c_str() );
293 
294  if ( value >= 0 )
295  {
296  const QString envValue( getenv( envVarName.toStdString().c_str() ) );
297  prioritize( QMap<QgsServerSettingsEnv::EnvVar, QString> { {( QgsServerSettingsEnv::EnvVar ) value, envValue } } );
298  rc = true;
299  }
300 
301  return rc;
302 }
303 
304 QMap<QgsServerSettingsEnv::EnvVar, QString> QgsServerSettings::getEnv() const
305 {
306  QMap<QgsServerSettingsEnv::EnvVar, QString> env;
307 
308  const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerSettingsEnv::EnvVar>() );
309  for ( int i = 0; i < metaEnum.keyCount(); i++ )
310  {
311  env[( QgsServerSettingsEnv::EnvVar ) metaEnum.value( i )] = getenv( metaEnum.key( i ) );
312  }
313 
314  return env;
315 }
316 
317 QVariant QgsServerSettings::value( QgsServerSettingsEnv::EnvVar envVar, bool actual ) const
318 {
319  if ( actual )
320  {
321  const QString envValue( getenv( name( envVar ).toStdString().c_str() ) );
322 
323  if ( ! envValue.isEmpty() )
324  return envValue;
325  }
326 
327  if ( mSettings[ envVar ].src == QgsServerSettingsEnv::DEFAULT_VALUE )
328  {
329  return mSettings[ envVar ].defaultVal;
330  }
331  else
332  {
333  return mSettings[ envVar ].val;
334  }
335 }
336 
337 void QgsServerSettings::loadQSettings( const QString &envOptPath ) const
338 {
339  if ( ! envOptPath.isEmpty() )
340  {
341  QSettings::setDefaultFormat( QSettings::IniFormat );
342  QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, envOptPath );
343  }
344 }
345 
346 void QgsServerSettings::prioritize( const QMap<QgsServerSettingsEnv::EnvVar, QString> &env )
347 {
348  const auto constKeys( env.keys() );
349  for ( const QgsServerSettingsEnv::EnvVar &e : constKeys )
350  {
351  Setting s = mSettings[ e ];
352 
353  QVariant varValue;
354  if ( ! env.value( e ).isEmpty() )
355  {
356  varValue.setValue( env.value( e ) );
357  }
358 
359  if ( ! varValue.isNull() && varValue.canConvert( s.type ) )
360  {
361  s.val = varValue;
363  }
364  else if ( ! s.iniKey.isEmpty() && QSettings().contains( s.iniKey ) && QSettings().value( s.iniKey ).canConvert( s.type ) )
365  {
366  s.val = QSettings().value( s.iniKey );
368  }
369  else
370  {
371  s.val = QVariant();
373  }
374 
375  // an empty string can be returned from QSettings. In this case, we want
376  // to use the default value
377  if ( s.type == QVariant::String && s.val.toString().isEmpty() )
378  {
379  s.val = QVariant();
381  }
382 
383  mSettings[ e ] = s;
384  }
385 }
386 
388 {
389  const QMetaEnum metaEnumEnv( QMetaEnum::fromType<QgsServerSettingsEnv::EnvVar>() );
390  return metaEnumEnv.valueToKey( env );
391 }
392 
394 {
395  const QMetaEnum metaEnumSrc( QMetaEnum::fromType<QgsServerSettingsEnv::Source>() );
396 
397  QgsMessageLog::logMessage( "QGIS Server Settings: ", "Server", Qgis::Info );
398  for ( const Setting &s : qgis::as_const( mSettings ) )
399  {
400  const QString src = metaEnumSrc.valueToKey( s.src );
401  const QString var = name( s.envVar );
402 
403  const QString msg = " - " + var + " / '" + s.iniKey + "' (" + s.descr + "): '" + value( s.envVar ).toString() + "' (read from " + src + ")";
404  QgsMessageLog::logMessage( msg, "Server", Qgis::Info );
405  }
406 
407  if ( ! iniFile().isEmpty() )
408  {
409  const QString msg = "Ini file used to initialize settings: " + iniFile();
410  QgsMessageLog::logMessage( msg, "Server", Qgis::Info );
411  }
412 }
413 
414 // getter
416 {
417  return QSettings().fileName();
418 }
419 
421 {
423 }
424 
426 {
427  return value( QgsServerSettingsEnv::QGIS_SERVER_MAX_THREADS ).toInt();
428 }
429 
431 {
432  return value( QgsServerSettingsEnv::QGIS_SERVER_LOG_FILE ).toString();
433 }
434 
436 {
437  return value( QgsServerSettingsEnv::QGIS_SERVER_LOG_STDERR ).toBool();
438 }
439 
441 {
442  return static_cast<Qgis::MessageLevel>( value( QgsServerSettingsEnv::QGIS_SERVER_LOG_LEVEL ).toInt() );
443 }
444 
446 {
447  return value( QgsServerSettingsEnv::QGIS_PROJECT_FILE ).toString();
448 }
449 
451 {
452  return value( QgsServerSettingsEnv::QGIS_SERVER_CACHE_SIZE ).toLongLong();
453 }
454 
456 {
457  return value( QgsServerSettingsEnv::QGIS_SERVER_CACHE_DIRECTORY ).toString();
458 }
459 
461 {
463 }
464 
466 {
468 }
469 
471 {
472  return value( QgsServerSettingsEnv::QGIS_SERVER_WMS_MAX_HEIGHT ).toInt();
473 }
474 
476 {
477  return value( QgsServerSettingsEnv::QGIS_SERVER_WMS_MAX_WIDTH ).toInt();
478 }
479 
481 {
483 }
484 
486 {
488 }
489 
491 {
493 }
494 
496 {
497  return value( QgsServerSettingsEnv::QGIS_SERVER_API_WFS3_MAX_LIMIT ).toLongLong();
498 }
499 
501 {
503 }
504 
506 {
508 }
509 
511 {
513 }
514 
516 {
517  return value( QgsServerSettingsEnv::QGIS_SERVER_LOG_PROFILE, false ).toBool();
518 }
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:89
@ None
Definition: qgis.h:94
@ Info
Definition: qgis.h:90
static QString pkgDataPath()
Returns the common root path of all application data directories.
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
EnvVar
Environment variables to configure the server.
@ QGIS_SERVER_IGNORE_BAD_LAYERS
Do not consider the whole project unavailable if it contains bad layers.
@ QGIS_SERVER_TRUST_LAYER_METADATA
Trust layer metadata. Improves project read time. (since QGIS 3.16).
@ QGIS_SERVER_OVERRIDE_SYSTEM_LOCALE
Override system locale (since QGIS 3.8)
@ QGIS_SERVER_LANDING_PAGE_PROJECTS_PG_CONNECTIONS
PostgreSQL connection strings used by the landing page service to find projects (since QGIS 3....
@ QGIS_SERVER_API_WFS3_MAX_LIMIT
Maximum value for "limit" in a features request, defaults to 10000 (since QGIS 3.10).
@ QGIS_SERVER_API_RESOURCES_DIRECTORY
Base directory where HTML templates and static assets (e.g. images, js and css files) are searched fo...
@ QGIS_SERVER_WMS_MAX_WIDTH
Maximum width for a WMS request. The most conservative between this and the project one is used (sinc...
@ QGIS_SERVER_WMS_MAX_HEIGHT
Maximum height for a WMS request. The most conservative between this and the project one is used (sin...
@ QGIS_SERVER_DISABLE_GETPRINT
Disabled WMS GetPrint request and don't load layouts. Improves project read time. (since QGIS 3....
@ QGIS_SERVER_SHOW_GROUP_SEPARATOR
Show group (thousands) separator when formatting numeric values, defaults to false (since QGIS 3....
@ QGIS_SERVER_LANDING_PAGE_PROJECTS_DIRECTORIES
Directories used by the landing page service to find .qgs and .qgz projects (since QGIS 3....
@ QGIS_SERVER_LOG_PROFILE
When QGIS_SERVER_LOG_LEVEL is 0 this flag adds to the logs detailed information about the time taken ...
QString cacheDirectory() const
Returns the cache directory.
bool getPrintDisabled() const
Returns true if WMS GetPrint request is disabled and the project's reading flag QgsProject::ReadFlag:...
QString landingPageProjectsPgConnections() const
Returns the PostgreSQL connection strings used by the landing page service to find projects.
int maxThreads() const
Returns the maximum number of threads to use.
bool logStderr() const
Returns whether logging to stderr is activated.
QgsServerSettings()
Constructor.
QString projectFile() const
Returns the QGS project file to use.
QString apiResourcesDirectory() const
Returns the server-wide base directory where HTML templates and static assets (e.g.
Qgis::MessageLevel logLevel() const
Returns the log level.
int wmsMaxWidth() const
Returns the server-wide max width of a WMS GetMap request.
static QString name(QgsServerSettingsEnv::EnvVar env)
Returns the string representation of a setting.
void logSummary() const
Log a summary of settings currently loaded.
QString logFile() const
Returns the log file.
qlonglong apiWfs3MaxLimit() const
Returns the server-wide maximum allowed value for "limit" in a features request.
int wmsMaxHeight() const
Returns the server-wide max height of a WMS GetMap request.
QString landingPageProjectsDirectories() const
Returns the directories used by the landing page service to find .qgs and .qgz projects.
bool parallelRendering() const
Returns parallel rendering setting.
bool showGroupSeparator() const
Show group (thousand) separator.
bool ignoreBadLayers() const
Returns true if the bad layers are ignored and false when the presence of a bad layers invalidates th...
QString iniFile() const
Returns the ini file loaded by QSetting.
bool logProfile()
Returns true if profile information has to be added to the logs, default value is false.
QString overrideSystemLocale() const
Overrides system locale.
bool trustLayerMetadata() const
Returns true if the reading flag trust layer metadata is activated.
void load()
Load settings according to current environment variables.
qint64 cacheSize() const
Returns the cache size.