Beispiel #1
0
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;
}
Beispiel #2
0
/**
 * @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 );
}
Beispiel #3
0
/**
 * @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();
}