/** * @brief Handles the request * @param queryString * @param returnBody * @param returnHeaders * @return response body and headers if mCaptureOutput is set and the * flags are set, empty QByteArray if not */ QByteArray QgsServer::handleRequest( const QString queryString , bool returnHeaders, bool returnBody ) { // Run init if handleRequest was called without previously initialising // the server if ( ! mInitialised ) { init( ); } /* * This is mainly for python bindings, passing QUERY_STRING * to handleRequest without using os.environment */ if ( ! queryString.isEmpty() ) { #ifdef _MSC_VER _putenv_s( "QUERY_STRING", queryString.toUtf8().data() ); #else setenv( "QUERY_STRING", queryString.toUtf8().data(), 1 ); #endif } int logLevel = QgsServerLogger::instance()->logLevel(); QTime time; //used for measuring request time if loglevel < 1 QgsMapLayerRegistry::instance()->removeAllMapLayers(); mQgsApplication->processEvents(); if ( logLevel < 1 ) { time.start(); printRequestInfos(); } //Request handler QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler( mCaptureOutput ) ); try { // TODO: split parse input into plain parse and processing from specific services theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsMessageLog::logMessage( "Parse input exception: " + e.message(), "Server", QgsMessageLog::CRITICAL ); theRequestHandler->setServiceException( e ); } #ifdef HAVE_SERVER_PYTHON_PLUGINS // Set the request handler into the interface for plugins to manipulate it mServerInterface->setRequestHandler( theRequestHandler.data() ); // Iterate filters and call their requestReady() method QgsServerFiltersMap::const_iterator filtersIterator; for ( filtersIterator = mServerInterface->filters().constBegin(); filtersIterator != mServerInterface->filters().constEnd(); ++filtersIterator ) { filtersIterator.value()->requestReady(); } //Pass the filters to the requestHandler, this is needed for the following reasons: // 1. allow core services to access plugin filters and implement thir own plugin hooks // 2. allow requestHandler to call sendResponse plugin hook theRequestHandler->setPluginFilters( mServerInterface->filters() ); #endif // Copy the parameters map QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() ); printRequestParameters( parameterMap, logLevel ); QMap<QString, QString>::const_iterator paramIt; //Config file path mConfigFilePath = configPath( mConfigFilePath, parameterMap ); #ifdef HAVE_SERVER_PYTHON_PLUGINS mServerInterface->setConfigFilePath( mConfigFilePath ); #endif //Service parameter QString serviceString = theRequestHandler->parameter( "SERVICE" ); if ( serviceString.isEmpty() ) { // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo QString requestString = theRequestHandler->parameter( "REQUEST" ); if ( requestString == "GetMap" || requestString == "GetFeatureInfo" ) { serviceString = "WMS"; } } // Enter core services main switch if ( !theRequestHandler->exceptionRaised() ) { if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( mConfigFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWCSServer wcsServer( mConfigFilePath, parameterMap, p, theRequestHandler.data() ); wcsServer.executeRequest(); } } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( mConfigFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWFSServer wfsServer( mConfigFilePath, parameterMap, p, theRequestHandler.data() ); wfsServer.executeRequest(); } } else if ( serviceString == "WMS" ) { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( mConfigFilePath, parameterMap ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading the project file or the SLD configuration" ) ); } else { QgsWMSServer wmsServer( mConfigFilePath, parameterMap, p, theRequestHandler.data(), mMapRenderer, mCapabilitiesCache ); wmsServer.executeRequest(); } } else { theRequestHandler->setServiceException( QgsMapServiceException( "Service configuration error", "Service unknown or unsupported" ) ); } // end switch } // end if not exception raised #ifdef HAVE_SERVER_PYTHON_PLUGINS // Iterate filters and call their responseComplete() method for ( filtersIterator = mServerInterface->filters().constBegin(); filtersIterator != mServerInterface->filters().constEnd(); ++filtersIterator ) { filtersIterator.value()->responseComplete(); } #endif theRequestHandler->sendResponse(); if ( logLevel < 1 ) { QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO ); } // TODO: if HAVE_SERVER_PYTHON // Returns the response bytestream return theRequestHandler->getResponse( returnHeaders , returnBody ); }
/** * @brief Handles the request * @param queryString * @return response headers and body */ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryString ) { // Run init if handleRequest was called without previously initialising // the server if ( ! mInitialised ) { init(); } /* * This is mainly for python bindings, passing QUERY_STRING * to handleRequest without using os.environment */ if ( ! queryString.isEmpty() ) putenv( "QUERY_STRING", queryString ); int logLevel = QgsServerLogger::instance()->logLevel(); QTime time; //used for measuring request time if loglevel < 1 QgsMapLayerRegistry::instance()->removeAllMapLayers(); mQgsApplication->processEvents(); if ( logLevel < 1 ) { time.start(); printRequestInfos(); } //Request handler QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler( mCaptureOutput ) ); try { // TODO: split parse input into plain parse and processing from specific services theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsMessageLog::logMessage( "Parse input exception: " + e.message(), "Server", QgsMessageLog::CRITICAL ); theRequestHandler->setServiceException( e ); } #ifdef HAVE_SERVER_PYTHON_PLUGINS // Set the request handler into the interface for plugins to manipulate it mServerInterface->setRequestHandler( theRequestHandler.data() ); // Iterate filters and call their requestReady() method QgsServerFiltersMap::const_iterator filtersIterator; QgsServerFiltersMap filters = mServerInterface->filters(); for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator ) { filtersIterator.value()->requestReady(); } //Pass the filters to the requestHandler, this is needed for the following reasons: // 1. allow core services to access plugin filters and implement thir own plugin hooks // 2. allow requestHandler to call sendResponse plugin hook theRequestHandler->setPluginFilters( mServerInterface->filters() ); #endif // Copy the parameters map QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() ); #ifdef HAVE_SERVER_PYTHON_PLUGINS const QgsAccessControl* accessControl = nullptr; accessControl = mServerInterface->accessControls(); #endif printRequestParameters( parameterMap, logLevel ); QMap<QString, QString>::const_iterator paramIt; //Config file path QString configFilePath = configPath( mConfigFilePath, parameterMap ); #ifdef HAVE_SERVER_PYTHON_PLUGINS mServerInterface->setConfigFilePath( configFilePath ); #endif //Service parameter QString serviceString = theRequestHandler->parameter( "SERVICE" ); if ( serviceString.isEmpty() ) { // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo QString requestString = theRequestHandler->parameter( "REQUEST" ); if ( requestString == "GetMap" || requestString == "GetFeatureInfo" ) { serviceString = "WMS"; } } //possibility for client to suggest a download filename QString outputFileName = theRequestHandler->parameter( "FILE_NAME" ); if ( !outputFileName.isEmpty() ) { theRequestHandler->setDefaultHeaders(); theRequestHandler->setHeader( "Content-Disposition", "attachment; filename=\"" + outputFileName + "\"" ); } // Enter core services main switch if ( !theRequestHandler->exceptionRaised() ) { if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", QString( "Error reading the project file: %1" ).arg( configFilePath ) ) ); } else { QgsWCSServer wcsServer( configFilePath , parameterMap , p , theRequestHandler.data() #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); wcsServer.executeRequest(); } } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", QString( "Error reading the project file: %1" ).arg( configFilePath ) ) ); } else { QgsWFSServer wfsServer( configFilePath , parameterMap , p , theRequestHandler.data() #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); wfsServer.executeRequest(); } } else if ( serviceString == "WMS" ) { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading the project file or the SLD configuration" ) ); } else { QgsWMSServer wmsServer( configFilePath , parameterMap , p , theRequestHandler.data() , mMapRenderer , mCapabilitiesCache #ifdef HAVE_SERVER_PYTHON_PLUGINS , accessControl #endif ); wmsServer.executeRequest(); } } else { theRequestHandler->setServiceException( QgsMapServiceException( "Service configuration error", "Service unknown or unsupported" ) ); } // end switch } // end if not exception raised #ifdef HAVE_SERVER_PYTHON_PLUGINS // Iterate filters and call their responseComplete() method filters = mServerInterface->filters(); for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator ) { filtersIterator.value()->responseComplete(); } // We are done using theRequestHandler in plugins, make sure we don't access // to a deleted request handler from Python bindings mServerInterface->clearRequestHandler(); #endif theRequestHandler->sendResponse(); if ( logLevel < 1 ) { QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO ); } // Returns the header and response bytestreams (to be used in Python bindings) return theRequestHandler->getResponse(); }
int main( int argc, char * argv[] ) { #ifndef _MSC_VER qInstallMsgHandler( dummyMessageHandler ); #endif QString optionsPath = getenv( "QGIS_OPTIONS_PATH" ); if ( !optionsPath.isEmpty() ) { QgsDebugMsg( "Options PATH: " + optionsPath ); QSettings::setDefaultFormat( QSettings::IniFormat ); QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, optionsPath ); } QgsApplication qgsapp( argc, argv, getenv( "DISPLAY" ) ); QCoreApplication::setOrganizationName( QgsApplication::QGIS_ORGANIZATION_NAME ); QCoreApplication::setOrganizationDomain( QgsApplication::QGIS_ORGANIZATION_DOMAIN ); QCoreApplication::setApplicationName( QgsApplication::QGIS_APPLICATION_NAME ); //Default prefix path may be altered by environment variable QgsApplication::init(); #if !defined(Q_OS_WIN) // init QGIS's paths - true means that all path will be inited from prefix QgsApplication::setPrefixPath( CMAKE_INSTALL_PREFIX, TRUE ); #endif #if defined(SERVER_SKIP_ECW) QgsDebugMsg( "Skipping GDAL ECW drivers in server." ); QgsApplication::skipGdalDriver( "ECW" ); QgsApplication::skipGdalDriver( "JP2ECW" ); #endif setupNetworkAccessManager(); QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars ); // Instantiate the plugin directory so that providers are loaded QgsProviderRegistry::instance( QgsApplication::pluginPath() ); QgsDebugMsg( "Prefix PATH: " + QgsApplication::prefixPath() ); QgsDebugMsg( "Plugin PATH: " + QgsApplication::pluginPath() ); QgsDebugMsg( "PkgData PATH: " + QgsApplication::pkgDataPath() ); QgsDebugMsg( "User DB PATH: " + QgsApplication::qgisUserDbFilePath() ); QgsDebugMsg( "SVG PATHS: " + QgsApplication::svgPaths().join( ":" ) ); QgsApplication::createDB(); //init qgis.db (e.g. necessary for user crs) QString defaultConfigFilePath; QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs file in the server directory if ( projectFileInfo.exists() ) { defaultConfigFilePath = projectFileInfo.absoluteFilePath(); QgsDebugMsg( "Using default project file: " + defaultConfigFilePath ); } else { QFileInfo adminSLDFileInfo = defaultAdminSLD(); if ( adminSLDFileInfo.exists() ) { defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath(); } } //create cache for capabilities XML QgsCapabilitiesCache capabilitiesCache; //creating QgsMapRenderer is expensive (access to srs.db), so we do it here before the fcgi loop QScopedPointer< QgsMapRenderer > theMapRenderer( new QgsMapRenderer ); theMapRenderer->setLabelingEngine( new QgsPalLabeling() ); #ifdef QGSMSDEBUG QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" ); #endif int logLevel = QgsServerLogger::instance()->logLevel(); QTime time; //used for measuring request time if loglevel < 1 #ifdef HAVE_SERVER_PYTHON_PLUGINS // Create the interface QgsServerInterfaceImpl serverIface( &capabilitiesCache ); // Init plugins if ( ! QgsServerPlugins::initPlugins( &serverIface ) ) { QgsMessageLog::logMessage( "No server python plugins are available", "Server", QgsMessageLog::INFO ); } else { QgsMessageLog::logMessage( "Server python plugins loaded", "Server", QgsMessageLog::INFO ); } // Store plugin filters for faster access QMultiMap<int, QgsServerFilter*> pluginFilters = serverIface.filters(); #endif QgsEditorWidgetRegistry::initEditors(); while ( fcgi_accept() >= 0 ) { QgsMapLayerRegistry::instance()->removeAllMapLayers(); qgsapp.processEvents(); if ( logLevel < 1 ) { time.start(); printRequestInfos(); } //Request handler QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler() ); try { // TODO: split parse input into plain parse and processing from specific services theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsMessageLog::logMessage( "Parse input exception: " + e.message(), "Server", QgsMessageLog::CRITICAL ); theRequestHandler->setServiceException( e ); } #ifdef HAVE_SERVER_PYTHON_PLUGINS // Set the request handler into the interface for plugins to manipulate it serverIface.setRequestHandler( theRequestHandler.data() ); // Iterate filters and call their requestReady() method QgsServerFiltersMap::const_iterator filtersIterator; for ( filtersIterator = pluginFilters.constBegin(); filtersIterator != pluginFilters.constEnd(); ++filtersIterator ) { filtersIterator.value()->requestReady(); } //Pass the filters to the requestHandler, this is needed for the following reasons: // 1. allow core services to access plugin filters and implement thir own plugin hooks // 2. allow requestHandler to call sendResponse plugin hook //TODO: implement this in the requestHandler ctor (far easier if we will get rid of // HAVE_SERVER_PYTHON_PLUGINS theRequestHandler->setPluginFilters( pluginFilters ); #endif // Copy the parameters map QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() ); printRequestParameters( parameterMap, logLevel ); QMap<QString, QString>::const_iterator paramIt; //Config file path QString configFilePath = configPath( defaultConfigFilePath, parameterMap ); //Service parameter QString serviceString = theRequestHandler->parameter( "SERVICE" ); if ( serviceString.isEmpty() ) { // SERVICE not mandatory for WMS 1.3.0 GetMap & GetFeatureInfo QString requestString = theRequestHandler->parameter( "REQUEST" ); if ( requestString == "GetMap" || requestString == "GetFeatureInfo" ) { serviceString = "WMS"; } } // Enter core services main switch if ( !theRequestHandler->exceptionRaised() ) { if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWCSServer wcsServer( configFilePath, parameterMap, p, theRequestHandler.data() ); wcsServer.executeRequest(); } } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "Project file error", "Error reading the project file" ) ); } else { QgsWFSServer wfsServer( configFilePath, parameterMap, p, theRequestHandler.data() ); wfsServer.executeRequest(); } } else if ( serviceString == "WMS" ) { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath, parameterMap ); if ( !p ) { theRequestHandler->setServiceException( QgsMapServiceException( "WMS configuration error", "There was an error reading the project file or the SLD configuration" ) ); } else { QgsWMSServer wmsServer( configFilePath, parameterMap, p, theRequestHandler.data(), theMapRenderer.data(), &capabilitiesCache ); wmsServer.executeRequest(); } } else { theRequestHandler->setServiceException( QgsMapServiceException( "Service configuration error", "Service unknown or unsupported" ) ); } // end switch } // end if not exception raised #ifdef HAVE_SERVER_PYTHON_PLUGINS // Iterate filters and call their responseComplete() method for ( filtersIterator = pluginFilters.constBegin(); filtersIterator != pluginFilters.constEnd(); ++filtersIterator ) { filtersIterator.value()->responseComplete(); } #endif theRequestHandler->sendResponse(); if ( logLevel < 1 ) { QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO ); } } return 0; }
int main( int argc, char * argv[] ) { #ifndef _MSC_VER qInstallMsgHandler( dummyMessageHandler ); #endif QgsApplication qgsapp( argc, argv, getenv( "DISPLAY" ) ); //Default prefix path may be altered by environment variable QgsApplication::init(); #if !defined(Q_OS_WIN) // init QGIS's paths - true means that all path will be inited from prefix QgsApplication::setPrefixPath( CMAKE_INSTALL_PREFIX, TRUE ); #endif #if defined(MAPSERVER_SKIP_ECW) QgsDebugMsg( "Skipping GDAL ECW drivers in server." ); QgsApplication::skipGdalDriver( "ECW" ); QgsApplication::skipGdalDriver( "JP2ECW" ); #endif setupNetworkAccessManager(); QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars ); // Instantiate the plugin directory so that providers are loaded QgsProviderRegistry::instance( QgsApplication::pluginPath() ); QgsDebugMsg( "Prefix PATH: " + QgsApplication::prefixPath() ); QgsDebugMsg( "Plugin PATH: " + QgsApplication::pluginPath() ); QgsDebugMsg( "PkgData PATH: " + QgsApplication::pkgDataPath() ); QgsDebugMsg( "User DB PATH: " + QgsApplication::qgisUserDbFilePath() ); QgsDebugMsg( qgsapp.applicationDirPath() + "/qgis_wms_server.log" ); QgsApplication::createDB(); //init qgis.db (e.g. necessary for user crs) QString defaultConfigFilePath; QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs file in the server directory if ( projectFileInfo.exists() ) { defaultConfigFilePath = projectFileInfo.absoluteFilePath(); QgsDebugMsg( "Using default project file: " + defaultConfigFilePath ); } else { QFileInfo adminSLDFileInfo = defaultAdminSLD(); if ( adminSLDFileInfo.exists() ) { defaultConfigFilePath = adminSLDFileInfo.absoluteFilePath(); } } //create cache for capabilities XML QgsCapabilitiesCache capabilitiesCache; //creating QgsMapRenderer is expensive (access to srs.db), so we do it here before the fcgi loop QgsMapRenderer* theMapRenderer = new QgsMapRenderer(); theMapRenderer->setLabelingEngine( new QgsPalLabeling() ); printRequestInfos(); #ifdef QGSMSDEBUG QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" ); #endif while ( fcgi_accept() >= 0 ) { printRequestInfos(); //print request infos if in debug mode //Request handler QgsRequestHandler* theRequestHandler = createRequestHandler(); QMap<QString, QString> parameterMap; try { parameterMap = theRequestHandler->parseInput(); } catch ( QgsMapServiceException& e ) { QgsDebugMsg( "An exception was thrown during input parsing" ); theRequestHandler->sendServiceException( e ); continue; } QMap<QString, QString>::const_iterator paramIt; //Config file path QString configFilePath = configPath( defaultConfigFilePath, parameterMap ); //Service parameter QString serviceString; paramIt = parameterMap.find( "SERVICE" ); if ( paramIt == parameterMap.constEnd() ) { theRequestHandler->sendServiceException( QgsMapServiceException( "ServiceNotSpecified", "Service not specified. The SERVICE parameter is mandatory" ) ); delete theRequestHandler; continue; } else { serviceString = paramIt.value(); } if ( serviceString == "WCS" ) { QgsWCSProjectParser* p = QgsConfigCache::instance()->wcsConfiguration( configFilePath ); if ( !p ) { //error handling } QgsWCSServer wcsServer( configFilePath, parameterMap, p, theRequestHandler ); wcsServer.executeRequest(); } else if ( serviceString == "WFS" ) { QgsWFSProjectParser* p = QgsConfigCache::instance()->wfsConfiguration( configFilePath ); if ( !p ) { //error handling } QgsWFSServer wfsServer( configFilePath, parameterMap, p, theRequestHandler ); wfsServer.executeRequest(); } else //WMS else { QgsWMSConfigParser* p = QgsConfigCache::instance()->wmsConfiguration( configFilePath, parameterMap ); if ( !p ) { //error handling } //adminConfigParser->loadLabelSettings( theMapRenderer->labelingEngine() ); QgsWMSServer wmsServer( configFilePath, parameterMap, p, theRequestHandler, theMapRenderer, &capabilitiesCache ); wmsServer.executeRequest(); } } delete theMapRenderer; return 0; }