예제 #1
0
    def dispatch(self, writer=sys.stdout, write_headers=True):
        """ Handle incoming HTTP request """

        if self.requesttype == 'GET':
            self.kvp = self.normalize_kvp(self.kvp)
            version_202 = ('version' in self.kvp and
                           self.kvp['version'] == '2.0.2')
            accept_version_202 = ('acceptversions' in self.kvp and
                                  '2.0.2' in self.kvp['acceptversions'])
            if version_202 or accept_version_202:
                self.request_version = '2.0.2'
        elif self.requesttype == 'POST':
            if self.request.find(b'2.0.2') != -1:
                self.request_version = '2.0.2'

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                self.kvp['mode'] == 'sru'):
            self.mode = 'sru'
            self.request_version = '2.0.2'
            LOGGER.info('SRU mode detected; processing request')
            self.kvp = self.sru().request_sru2csw(self.kvp)

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                self.kvp['mode'] == 'oaipmh'):
            self.mode = 'oaipmh'
            self.request_version = '2.0.2'
            LOGGER.info('OAI-PMH mode detected; processing request.')
            self.oaiargs = dict((k, v) for k, v in self.kvp.items() if k)
            self.kvp = self.oaipmh().request(self.kvp)

        if self.request_version == '2.0.2':
            self.iface = csw2.Csw2(server_csw=self)
            self.context.set_model('csw')

        # configure transaction support, if specified in config
        self._gen_manager()

        namespaces = self.context.namespaces
        ops = self.context.model['operations']
        constraints = self.context.model['constraints']
        # generate domain model
        # NOTE: We should probably avoid this sort of mutable state for WSGI
        if 'GetDomain' not in ops:
            ops['GetDomain'] = self.context.gen_domains()

        # generate distributed search model, if specified in config
        if self.config.has_option('server', 'federatedcatalogues'):
            LOGGER.info('Configuring distributed search')

            constraints['FederatedCatalogues'] = {'values': []}

            for fedcat in self.config.get('server',
                                          'federatedcatalogues').split(','):
                LOGGER.debug('federated catalogue: %s', fedcat)
                constraints['FederatedCatalogues']['values'].append(fedcat)

        for key, value in self.outputschemas.items():
            get_records_params = ops['GetRecords']['parameters']
            get_records_params['outputSchema']['values'].append(
                value.NAMESPACE)
            get_records_by_id_params = ops['GetRecordById']['parameters']
            get_records_by_id_params['outputSchema']['values'].append(
                value.NAMESPACE)
            if 'Harvest' in ops:
                harvest_params = ops['Harvest']['parameters']
                harvest_params['ResourceType']['values'].append(
                    value.NAMESPACE)

        LOGGER.info('Setting MaxRecordDefault')
        if self.config.has_option('server', 'maxrecords'):
            constraints['MaxRecordDefault']['values'] = [
                self.config.get('server', 'maxrecords')]

        # load profiles
        if self.config.has_option('server', 'profiles'):
            self.profiles = pprofile.load_profiles(
                os.path.join('pycsw', 'plugins', 'profiles'),
                pprofile.Profile,
                self.config.get('server', 'profiles')
            )

            for prof in self.profiles['plugins'].keys():
                tmp = self.profiles['plugins'][prof](self.context.model,
                                                     namespaces,
                                                     self.context)

                key = tmp.outputschema  # to ref by outputschema
                self.profiles['loaded'][key] = tmp
                self.profiles['loaded'][key].extend_core(self.context.model,
                                                         namespaces,
                                                         self.config)

            LOGGER.debug('Profiles loaded: %s' % list(self.profiles['loaded'].keys()))

        # init repository
        # look for tablename, set 'records' as default
        if not self.config.has_option('repository', 'table'):
            self.config.set('repository', 'table', 'records')

        repo_filter = None
        if self.config.has_option('repository', 'filter'):
            repo_filter = self.config.get('repository', 'filter')

        if self.config.has_option('repository', 'source'):  # load custom repository
            rs = self.config.get('repository', 'source')
            rs_modname, rs_clsname = rs.rsplit('.', 1)

            rs_mod = __import__(rs_modname, globals(), locals(), [rs_clsname])
            rs_cls = getattr(rs_mod, rs_clsname)

            try:
                self.repository = rs_cls(self.context, repo_filter)
                LOGGER.debug('Custom repository %s loaded (%s)', rs, self.repository.dbtype)
            except Exception as err:
                msg = 'Could not load custom repository'
                LOGGER.exception(msg)
                self.response = self.iface.exceptionreport(
                    'NoApplicableCode', 'service', msg)

        else:  # load default repository
            self.orm = 'sqlalchemy'
            from pycsw.core import repository
            try:
                LOGGER.info('Loading default repository')
                self.repository = repository.Repository(
                    self.config.get('repository', 'database'),
                    self.context,
                    self.environ.get('local.app_root', None),
                    self.config.get('repository', 'table'),
                    repo_filter
                )
                LOGGER.debug(
                    'Repository loaded (local): %s.' % self.repository.dbtype)
            except Exception as err:
                msg = 'Could not load repository (local)'
                LOGGER.exception(msg)
                self.response = self.iface.exceptionreport(
                    'NoApplicableCode', 'service', msg)

        if self.requesttype == 'POST':
            LOGGER.debug('HTTP POST request')
            LOGGER.debug('CSW version: %s', self.iface.version)
            self.kvp = self.iface.parse_postdata(self.request)

        error = 0

        if isinstance(self.kvp, str):  # it's an exception
            error = 1
            locator = 'service'
            text = self.kvp
            if (self.kvp.find('the document is not valid') != -1 or
                    self.kvp.find('document not well-formed') != -1):
                code = 'NoApplicableCode'
            else:
                code = 'InvalidParameterValue'

        LOGGER.debug('HTTP Headers:\n%s.', self.environ)
        LOGGER.debug('Parsed request parameters: %s', self.kvp)

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                self.kvp['mode'] == 'opensearch'):
            self.mode = 'opensearch'
            LOGGER.info('OpenSearch mode detected; processing request.')
            self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if ((len(self.kvp) == 0 and self.request_version == '3.0.0') or
                (len(self.kvp) == 1 and 'config' in self.kvp)):
            LOGGER.info('Turning on default csw30:Capabilities for base URL')
            self.kvp = {
                'service': 'CSW',
                'acceptversions': '3.0.0',
                'request': 'GetCapabilities'
            }
            http_accept = self.environ.get('HTTP_ACCEPT', '')
            if 'application/opensearchdescription+xml' in http_accept:
                self.mode = 'opensearch'
                self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if error == 0:
            # test for the basic keyword values (service, version, request)
            basic_options = ['service', 'request']
            request = self.kvp.get('request', '')
            own_version_integer = util.get_version_integer(
                self.request_version)
            if self.request_version == '2.0.2':
                basic_options.append('version')

            for k in basic_options:
                if k not in self.kvp:
                    if (k in ['version', 'acceptversions'] and
                            request == 'GetCapabilities'):
                        pass
                    else:
                        error = 1
                        locator = k
                        code = 'MissingParameterValue'
                        text = 'Missing keyword: %s' % k
                        break

            # test each of the basic keyword values
            if error == 0:
                # test service
                if self.kvp['service'] != 'CSW':
                    error = 1
                    locator = 'service'
                    code = 'InvalidParameterValue'
                    text = 'Invalid value for service: %s.\
                    Value MUST be CSW' % self.kvp['service']

                # test version
                kvp_version = self.kvp.get('version', '')
                try:
                    kvp_version_integer = util.get_version_integer(kvp_version)
                except Exception as err:
                    kvp_version_integer = 'invalid_value'
                if (request != 'GetCapabilities' and
                        kvp_version_integer != own_version_integer):
                    error = 1
                    locator = 'version'
                    code = 'InvalidParameterValue'
                    text = ('Invalid value for version: %s. Value MUST be '
                            '2.0.2 or 3.0.0' % kvp_version)

                # check for GetCapabilities acceptversions
                if 'acceptversions' in self.kvp:
                    for vers in self.kvp['acceptversions'].split(','):
                        vers_integer = util.get_version_integer(vers)
                        if vers_integer == own_version_integer:
                            break
                        else:
                            error = 1
                            locator = 'acceptversions'
                            code = 'VersionNegotiationFailed'
                            text = ('Invalid parameter value in '
                                    'acceptversions: %s. Value MUST be '
                                    '2.0.2 or 3.0.0' %
                                    self.kvp['acceptversions'])

                # test request
                if self.kvp['request'] not in \
                    self.context.model['operations']:
                    error = 1
                    locator = 'request'
                    if request in ['Transaction', 'Harvest']:
                        code = 'OperationNotSupported'
                        text = '%s operations are not supported' % request
                    else:
                        code = 'InvalidParameterValue'
                        text = 'Invalid value for request: %s' % request

        if error == 1:  # return an ExceptionReport
            LOGGER.error('basic service options error: %s, %s, %s', code, locator, text)
            self.response = self.iface.exceptionreport(code, locator, text)

        else:  # process per the request value

            if 'responsehandler' in self.kvp:
                # set flag to process asynchronously
                import threading
                self.async = True
                request_id = self.kvp.get('requestid', None)
                if request_id is None:
                    import uuid
                    self.kvp['requestid'] = str(uuid.uuid4())

            if self.kvp['request'] == 'GetCapabilities':
                self.response = self.iface.getcapabilities()
            elif self.kvp['request'] == 'DescribeRecord':
                self.response = self.iface.describerecord()
            elif self.kvp['request'] == 'GetDomain':
                self.response = self.iface.getdomain()
            elif self.kvp['request'] == 'GetRecords':
                if self.async:  # process asynchronously
                    threading.Thread(target=self.iface.getrecords).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.getrecords()
            elif self.kvp['request'] == 'GetRecordById':
                self.response = self.iface.getrecordbyid()
            elif self.kvp['request'] == 'GetRepositoryItem':
                self.response = self.iface.getrepositoryitem()
            elif self.kvp['request'] == 'Transaction':
                self.response = self.iface.transaction()
            elif self.kvp['request'] == 'Harvest':
                if self.async:  # process asynchronously
                    threading.Thread(target=self.iface.harvest).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.harvest()
            else:
                self.response = self.iface.exceptionreport(
                    'InvalidParameterValue', 'request',
                    'Invalid request parameter: %s' % self.kvp['request']
                )

        LOGGER.info('Request processed')
        if self.mode == 'sru':
            LOGGER.info('SRU mode detected; processing response.')
            self.response = self.sru().response_csw2sru(self.response,
                                                        self.environ)
        elif self.mode == 'opensearch':
            LOGGER.info('OpenSearch mode detected; processing response.')
            self.response = self.opensearch().response_csw2opensearch(
                self.response, self.config)

        elif self.mode == 'oaipmh':
            LOGGER.info('OAI-PMH mode detected; processing response.')
            self.response = self.oaipmh().response(
                self.response, self.oaiargs, self.repository,
                self.config.get('server', 'url')
            )

        return self._write_response()
예제 #2
0
    def dispatch(self, writer=sys.stdout, write_headers=True):
        ''' Handle incoming HTTP request '''

        if self.requesttype == 'GET':
            self.kvp = self.normalize_kvp(self.kvp)
            if (('version' in self.kvp and self.kvp['version'] == '2.0.2')
                    or ('acceptversions' in self.kvp
                        and '2.0.2' in self.kvp['acceptversions'])):
                self.request_version = '2.0.2'
        elif self.requesttype == 'POST':
            if self.request.find('2.0.2') != -1:
                self.request_version = '2.0.2'

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp
                and self.kvp['mode'] == 'sru'):
            self.mode = 'sru'
            self.request_version = '2.0.2'
            LOGGER.debug('SRU mode detected; processing request.')
            self.kvp = self.sru().request_sru2csw(self.kvp)

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp
                and self.kvp['mode'] == 'oaipmh'):
            self.mode = 'oaipmh'
            self.request_version = '2.0.2'
            LOGGER.debug('OAI-PMH mode detected; processing request.')
            self.oaiargs = dict((k, v) for k, v in self.kvp.items() if k)
            self.kvp = self.oaipmh().request(self.kvp)

        if self.request_version == '2.0.2':
            self.iface = csw2.Csw2(server_csw=self)
            self.context.set_model('csw')

        # configure transaction support, if specified in config
        self._gen_manager()

        # generate domain model
        # NOTE: We should probably avoid this sort of mutable state for WSGI
        if 'GetDomain' not in self.context.model['operations']:
            self.context.model['operations']['GetDomain'] = \
            self.context.gen_domains()

        # generate distributed search model, if specified in config
        if self.config.has_option('server', 'federatedcatalogues'):
            LOGGER.debug('Configuring distributed search.')

            self.context.model['constraints']['FederatedCatalogues'] = \
            {'values': []}

            for fedcat in \
            self.config.get('server', 'federatedcatalogues').split(','):
                self.context.model\
                ['constraints']['FederatedCatalogues']['values'].append(fedcat)

        for key, value in self.outputschemas.iteritems():
            self.context.model['operations']['GetRecords']['parameters'][
                'outputSchema']['values'].append(value.NAMESPACE)
            self.context.model['operations']['GetRecordById']['parameters'][
                'outputSchema']['values'].append(value.NAMESPACE)
            if 'Harvest' in self.context.model['operations']:
                self.context.model['operations']['Harvest']['parameters'][
                    'ResourceType']['values'].append(value.NAMESPACE)

        LOGGER.debug('Setting MaxRecordDefault')
        if self.config.has_option('server', 'maxrecords'):
            self.context.model['constraints']['MaxRecordDefault']['values'] = \
            [self.config.get('server', 'maxrecords')]

        # load profiles
        if self.config.has_option('server', 'profiles'):
            self.profiles = pprofile.load_profiles(
                os.path.join('pycsw', 'plugins', 'profiles'), pprofile.Profile,
                self.config.get('server', 'profiles'))

            for prof in self.profiles['plugins'].keys():
                tmp = self.profiles['plugins'][prof](self.context.model,
                                                     self.context.namespaces,
                                                     self.context)

                key = tmp.outputschema  # to ref by outputschema
                self.profiles['loaded'][key] = tmp
                self.profiles['loaded'][key].extend_core(
                    self.context.model, self.context.namespaces, self.config)

            LOGGER.debug('Profiles loaded: %s.' %
                         self.profiles['loaded'].keys())

        # init repository
        # look for tablename, set 'records' as default
        if not self.config.has_option('repository', 'table'):
            self.config.set('repository', 'table', 'records')

        repo_filter = None
        if self.config.has_option('repository', 'filter'):
            repo_filter = self.config.get('repository', 'filter')

        if (self.config.has_option('repository', 'source')
                and self.config.get('repository', 'source') == 'geonode'):

            # load geonode repository
            from pycsw.plugins.repository.geonode import geonode_

            try:
                self.repository = \
                geonode_.GeoNodeRepository(self.context)
                LOGGER.debug('GeoNode repository loaded (geonode): %s.' % \
                self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                    'NoApplicableCode', 'service',
                    'Could not load repository (geonode): %s' % str(err))

        elif (self.config.has_option('repository', 'source')
              and self.config.get('repository', 'source') == 'odc'):

            # load odc repository
            from pycsw.plugins.repository.odc import odc

            try:
                self.repository = \
                odc.OpenDataCatalogRepository(self.context)
                LOGGER.debug('OpenDataCatalog repository loaded (geonode): %s.' % \
                self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                    'NoApplicableCode', 'service',
                    'Could not load repository (odc): %s' % str(err))

        else:  # load default repository
            self.orm = 'sqlalchemy'
            from pycsw.core import repository
            try:
                self.repository = \
                repository.Repository(self.config.get('repository', 'database'),
                self.context, self.environ.get('local.app_root', None),
                self.config.get('repository', 'table'), repo_filter)
                LOGGER.debug('Repository loaded (local): %s.' \
                % self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                    'NoApplicableCode', 'service',
                    'Could not load repository (local): %s' % str(err))

        if self.requesttype == 'POST':
            LOGGER.debug(self.iface.version)
            self.kvp = self.iface.parse_postdata(self.request)

        error = 0

        if isinstance(self.kvp, str):  # it's an exception
            error = 1
            locator = 'service'
            text = self.kvp
            if (self.kvp.find('the document is not valid') != -1
                    or self.kvp.find('document not well-formed') != -1):
                code = 'NoApplicableCode'
            else:
                code = 'InvalidParameterValue'

        LOGGER.debug('HTTP Headers:\n%s.' % self.environ)
        LOGGER.debug('Parsed request parameters: %s' % self.kvp)

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp
                and self.kvp['mode'] == 'opensearch'):
            self.mode = 'opensearch'
            LOGGER.debug('OpenSearch mode detected; processing request.')
            self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if ((self.kvp == {
                '': ''
        } and self.request_version == '3.0.0')
                or (len(self.kvp) == 1 and 'config' in self.kvp)):
            LOGGER.debug('Turning on default csw30:Capabilities for base URL')
            self.kvp = {
                'service': 'CSW',
                'acceptversions': '3.0.0',
                'request': 'GetCapabilities'
            }
            if 'HTTP_ACCEPT' in self.environ and 'application/opensearchdescription+xml' in self.environ[
                    'HTTP_ACCEPT']:
                self.mode = 'opensearch'
                self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if error == 0:
            # test for the basic keyword values (service, version, request)
            basic_options = ['service', 'request']
            if self.request_version == '2.0.2':
                basic_options.append('version')

            for k in basic_options:
                if k not in self.kvp:
                    if (k in ['version', 'acceptversions']
                            and 'request' in self.kvp
                            and self.kvp['request'] == 'GetCapabilities'):
                        pass
                    else:
                        error = 1
                        locator = k
                        code = 'MissingParameterValue'
                        text = 'Missing keyword: %s' % k
                        break

            # test each of the basic keyword values
            if error == 0:
                # test service
                if self.kvp['service'] != 'CSW':
                    error = 1
                    locator = 'service'
                    code = 'InvalidParameterValue'
                    text = 'Invalid value for service: %s.\
                    Value MUST be CSW' % self.kvp['service']

                # test version
                if ('version' in self.kvp
                        and util.get_version_integer(self.kvp['version']) !=
                        util.get_version_integer(self.request_version)
                        and self.kvp['request'] != 'GetCapabilities'):
                    error = 1
                    locator = 'version'
                    code = 'InvalidParameterValue'
                    text = 'Invalid value for version: %s.\
                    Value MUST be 2.0.2 or 3.0.0' % self.kvp['version']

                # check for GetCapabilities acceptversions
                if 'acceptversions' in self.kvp:
                    for vers in self.kvp['acceptversions'].split(','):
                        if (util.get_version_integer(vers) ==
                                util.get_version_integer(
                                    self.request_version)):
                            break
                        else:
                            error = 1
                            locator = 'acceptversions'
                            code = 'VersionNegotiationFailed'
                            text = 'Invalid parameter value in acceptversions:\
                            %s. Value MUST be 2.0.2 or 3.0.0'                                                              % \
                            self.kvp['acceptversions']

                # test request
                if self.kvp['request'] not in \
                    self.context.model['operations'].keys():
                    error = 1
                    locator = 'request'
                    if self.kvp['request'] in ['Transaction', 'Harvest']:
                        code = 'OperationNotSupported'
                        text = '%s operations are not supported' % \
                        self.kvp['request']
                    else:
                        code = 'InvalidParameterValue'
                        text = 'Invalid value for request: %s' % \
                        self.kvp['request']

        if error == 1:  # return an ExceptionReport
            self.response = self.iface.exceptionreport(code, locator, text)

        else:  # process per the request value

            if 'responsehandler' in self.kvp:
                # set flag to process asynchronously
                import threading
                self. async = True
                if ('requestid' not in self.kvp
                        or self.kvp['requestid'] is None):
                    import uuid
                    self.kvp['requestid'] = str(uuid.uuid4())

            if self.kvp['request'] == 'GetCapabilities':
                self.response = self.iface.getcapabilities()
            elif self.kvp['request'] == 'DescribeRecord':
                self.response = self.iface.describerecord()
            elif self.kvp['request'] == 'GetDomain':
                self.response = self.iface.getdomain()
            elif self.kvp['request'] == 'GetRecords':
                if self. async:  # process asynchronously
                    threading.Thread(target=self.iface.getrecords).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.getrecords()
            elif self.kvp['request'] == 'GetRecordById':
                self.response = self.iface.getrecordbyid()
            elif self.kvp['request'] == 'GetRepositoryItem':
                self.response = self.iface.getrepositoryitem()
            elif self.kvp['request'] == 'Transaction':
                self.response = self.iface.transaction()
            elif self.kvp['request'] == 'Harvest':
                if self. async:  # process asynchronously
                    threading.Thread(target=self.iface.harvest).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.harvest()
            else:
                self.response = self.iface.exceptionreport(
                    'InvalidParameterValue', 'request',
                    'Invalid request parameter: %s' % self.kvp['request'])

        if self.mode == 'sru':
            LOGGER.debug('SRU mode detected; processing response.')
            self.response = self.sru().response_csw2sru(
                self.response, self.environ)
        elif self.mode == 'opensearch':
            LOGGER.debug('OpenSearch mode detected; processing response.')
            self.response = self.opensearch().response_csw2opensearch(
                self.response, self.config)

        elif self.mode == 'oaipmh':
            LOGGER.debug('OAI-PMH mode detected; processing response.')
            self.response = self.oaipmh().response(
                self.response, self.oaiargs, self.repository,
                self.config.get('server', 'url'))

        return self._write_response()
예제 #3
0
파일: server.py 프로젝트: bstroebl/pycsw
    def dispatch(self, writer=sys.stdout, write_headers=True):
        ''' Handle incoming HTTP request '''

        if self.requesttype == 'GET':
            self.kvp = self.normalize_kvp(self.kvp)
            if (('version' in self.kvp and self.kvp['version'] == '2.0.2') or
                ('acceptversions' in self.kvp and '2.0.2' in self.kvp['acceptversions'])):
                self.request_version = '2.0.2'
        elif self.requesttype == 'POST':
            if self.request.find('2.0.2') != -1:
                self.request_version = '2.0.2'

        if (not isinstance(self.kvp, str) and
        'mode' in self.kvp and self.kvp['mode'] == 'sru'):
            self.mode = 'sru'
            self.request_version = '2.0.2'
            LOGGER.debug('SRU mode detected; processing request.')
            self.kvp = self.sru().request_sru2csw(self.kvp)

        if (not isinstance(self.kvp, str) and
        'mode' in self.kvp and self.kvp['mode'] == 'oaipmh'):
            self.mode = 'oaipmh'
            self.request_version = '2.0.2'
            LOGGER.debug('OAI-PMH mode detected; processing request.')
            self.oaiargs =  dict((k, v) for k, v in self.kvp.items() if k)
            self.kvp = self.oaipmh().request(self.kvp)

        if self.request_version == '2.0.2':
            self.iface = csw2.Csw2(server_csw=self)
            self.context.set_model('csw')

        # configure transaction support, if specified in config
        self._gen_manager()

        # generate domain model
        # NOTE: We should probably avoid this sort of mutable state for WSGI
        if 'GetDomain' not in self.context.model['operations']:
            self.context.model['operations']['GetDomain'] = \
            self.context.gen_domains()

        # generate distributed search model, if specified in config
        if self.config.has_option('server', 'federatedcatalogues'):
            LOGGER.debug('Configuring distributed search.')

            self.context.model['constraints']['FederatedCatalogues'] = \
            {'values': []}

            for fedcat in \
            self.config.get('server', 'federatedcatalogues').split(','):
                self.context.model\
                ['constraints']['FederatedCatalogues']['values'].append(fedcat)

        for key, value in self.outputschemas.iteritems():
            self.context.model['operations']['GetRecords']['parameters']['outputSchema']['values'].append(value.NAMESPACE)
            self.context.model['operations']['GetRecordById']['parameters']['outputSchema']['values'].append(value.NAMESPACE)
            if 'Harvest' in self.context.model['operations']:
                self.context.model['operations']['Harvest']['parameters']['ResourceType']['values'].append(value.NAMESPACE)

        LOGGER.debug('Setting MaxRecordDefault')
        if self.config.has_option('server', 'maxrecords'):
            self.context.model['constraints']['MaxRecordDefault']['values'] = \
            [self.config.get('server', 'maxrecords')]

        # load profiles
        if self.config.has_option('server', 'profiles'):
            self.profiles = pprofile.load_profiles(
            os.path.join('pycsw', 'plugins', 'profiles'),
            pprofile.Profile,
            self.config.get('server', 'profiles'))

            for prof in self.profiles['plugins'].keys():
                tmp = self.profiles['plugins'][prof](self.context.model,
                self.context.namespaces, self.context)

                key = tmp.outputschema  # to ref by outputschema
                self.profiles['loaded'][key] = tmp
                self.profiles['loaded'][key].extend_core(
                self.context.model, self.context.namespaces,
                self.config)

            LOGGER.debug('Profiles loaded: %s.' %
            self.profiles['loaded'].keys())

        # init repository
        # look for tablename, set 'records' as default
        if not self.config.has_option('repository', 'table'):
            self.config.set('repository', 'table', 'records')

        repo_filter = None
        if self.config.has_option('repository', 'filter'):
            repo_filter = self.config.get('repository', 'filter')

        if (self.config.has_option('repository', 'source') and
            self.config.get('repository', 'source') == 'geonode'):

            # load geonode repository
            from pycsw.plugins.repository.geonode import geonode_

            try:
                self.repository = \
                geonode_.GeoNodeRepository(self.context)
                LOGGER.debug('GeoNode repository loaded (geonode): %s.' % \
                self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                'NoApplicableCode', 'service',
                'Could not load repository (geonode): %s' % str(err))

        elif (self.config.has_option('repository', 'source') and
            self.config.get('repository', 'source') == 'odc'):

            # load odc repository
            from pycsw.plugins.repository.odc import odc

            try:
                self.repository = \
                odc.OpenDataCatalogRepository(self.context)
                LOGGER.debug('OpenDataCatalog repository loaded (geonode): %s.' % \
                self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                'NoApplicableCode', 'service',
                'Could not load repository (odc): %s' % str(err))

        else:  # load default repository
            self.orm = 'sqlalchemy'
            from pycsw.core import repository
            try:
                self.repository = \
                repository.Repository(self.config.get('repository', 'database'),
                self.context, self.environ.get('local.app_root', None),
                self.config.get('repository', 'table'), repo_filter)
                LOGGER.debug('Repository loaded (local): %s.' \
                % self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                'NoApplicableCode', 'service',
                'Could not load repository (local): %s' % str(err))

        if self.requesttype == 'POST':
            LOGGER.debug(self.iface.version)
            self.kvp = self.iface.parse_postdata(self.request)

        error = 0

        if isinstance(self.kvp, str):  # it's an exception
            error = 1
            locator = 'service'
            text = self.kvp
            if (self.kvp.find('the document is not valid') != -1 or
                self.kvp.find('document not well-formed') != -1):
                code = 'NoApplicableCode'
            else:
                code = 'InvalidParameterValue'

        LOGGER.debug('HTTP Headers:\n%s.' % self.environ)
        LOGGER.debug('Parsed request parameters: %s' % self.kvp)

        if (not isinstance(self.kvp, str) and
        'mode' in self.kvp and self.kvp['mode'] == 'opensearch'):
            self.mode = 'opensearch'
            LOGGER.debug('OpenSearch mode detected; processing request.')
            self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if ((self.kvp == {'': ''} and self.request_version == '3.0.0') or
            (len(self.kvp) == 1 and 'config' in self.kvp)):
            LOGGER.debug('Turning on default csw30:Capabilities for base URL')
            self.kvp = {
                'service': 'CSW',
                'acceptversions': '3.0.0',
                'request': 'GetCapabilities'
            }
            if 'HTTP_ACCEPT' in self.environ and 'application/opensearchdescription+xml' in self.environ['HTTP_ACCEPT']:
                self.mode = 'opensearch'
                self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if error == 0:
            # test for the basic keyword values (service, version, request)
            basic_options = ['service', 'request']
            if self.request_version == '2.0.2':
                basic_options.append('version')

            for k in basic_options:
                if k not in self.kvp:
                    if (k in ['version', 'acceptversions'] and 'request' in self.kvp and
                    self.kvp['request'] == 'GetCapabilities'):
                        pass
                    else:
                        error   = 1
                        locator = k
                        code = 'MissingParameterValue'
                        text = 'Missing keyword: %s' % k
                        break

            # test each of the basic keyword values
            if error == 0:
                # test service
                if self.kvp['service'] != 'CSW':
                    error = 1
                    locator = 'service'
                    code = 'InvalidParameterValue'
                    text = 'Invalid value for service: %s.\
                    Value MUST be CSW' % self.kvp['service']

                # test version
                if ('version' in self.kvp and
                    util.get_version_integer(self.kvp['version']) !=
                    util.get_version_integer(self.request_version) and
                    self.kvp['request'] != 'GetCapabilities'):
                    error = 1
                    locator = 'version'
                    code = 'InvalidParameterValue'
                    text = 'Invalid value for version: %s.\
                    Value MUST be 2.0.2 or 3.0.0' % self.kvp['version']

                # check for GetCapabilities acceptversions
                if 'acceptversions' in self.kvp:
                    for vers in self.kvp['acceptversions'].split(','):
                        if (util.get_version_integer(vers) ==
                            util.get_version_integer(self.request_version)):
                            break
                        else:
                            error = 1
                            locator = 'acceptversions'
                            code = 'VersionNegotiationFailed'
                            text = 'Invalid parameter value in acceptversions:\
                            %s. Value MUST be 2.0.2 or 3.0.0' % \
                            self.kvp['acceptversions']

                # test request
                if self.kvp['request'] not in \
                    self.context.model['operations'].keys():
                    error = 1
                    locator = 'request'
                    if self.kvp['request'] in ['Transaction','Harvest']:
                        code = 'OperationNotSupported'
                        text = '%s operations are not supported' % \
                        self.kvp['request']
                    else:
                        code = 'InvalidParameterValue'
                        text = 'Invalid value for request: %s' % \
                        self.kvp['request']

        if error == 1:  # return an ExceptionReport
            self.response = self.iface.exceptionreport(code, locator, text)

        else:  # process per the request value

            if 'responsehandler' in self.kvp:
                # set flag to process asynchronously
                import threading
                self.async = True
                if ('requestid' not in self.kvp
                or self.kvp['requestid'] is None):
                    import uuid
                    self.kvp['requestid'] = str(uuid.uuid4())

            if self.kvp['request'] == 'GetCapabilities':
                self.response = self.iface.getcapabilities()
            elif self.kvp['request'] == 'DescribeRecord':
                self.response = self.iface.describerecord()
            elif self.kvp['request'] == 'GetDomain':
                self.response = self.iface.getdomain()
            elif self.kvp['request'] == 'GetRecords':
                if self.async:  # process asynchronously
                    threading.Thread(target=self.iface.getrecords).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.getrecords()
            elif self.kvp['request'] == 'GetRecordById':
                self.response = self.iface.getrecordbyid()
            elif self.kvp['request'] == 'GetRepositoryItem':
                self.response = self.iface.getrepositoryitem()
            elif self.kvp['request'] == 'Transaction':
                self.response = self.iface.transaction()
            elif self.kvp['request'] == 'Harvest':
                if self.async:  # process asynchronously
                    threading.Thread(target=self.iface.harvest).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.harvest()
            else:
                self.response = self.iface.exceptionreport('InvalidParameterValue',
                'request', 'Invalid request parameter: %s' %
                self.kvp['request'])

        if self.mode == 'sru':
            LOGGER.debug('SRU mode detected; processing response.')
            self.response = self.sru().response_csw2sru(self.response,
                            self.environ)
        elif self.mode == 'opensearch':
            LOGGER.debug('OpenSearch mode detected; processing response.')
            self.response = self.opensearch().response_csw2opensearch(
                            self.response, self.config)

        elif self.mode == 'oaipmh':
            LOGGER.debug('OAI-PMH mode detected; processing response.')
            self.response = self.oaipmh().response(self.response,
                            self.oaiargs, self.repository, self.config.get('server', 'url'))

        return self._write_response()
예제 #4
0
    def dispatch(self, writer=sys.stdout, write_headers=True):
        """ Handle incoming HTTP request """

        error = 0
        if self.requesttype == 'GET':
            self.kvp = self.normalize_kvp(self.kvp)
            version_202 = ('version' in self.kvp and
                           self.kvp['version'] == '2.0.2')
            accept_version_202 = ('acceptversions' in self.kvp and
                                  '2.0.2' in self.kvp['acceptversions'])
            if version_202 or accept_version_202:
                self.request_version = '2.0.2'
        elif self.requesttype == 'POST':
            if self.request.find(b'cat/csw/2.0.2') != -1:
                self.request_version = '2.0.2'
            elif self.request.find(b'cat/csw/3.0') != -1:
                self.request_version = '3.0.0'

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                self.kvp['mode'] == 'sru'):
            self.mode = 'sru'
            self.request_version = '2.0.2'
            LOGGER.info('SRU mode detected; processing request')
            self.kvp = self.sru().request_sru2csw(self.kvp)

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                self.kvp['mode'] == 'oaipmh'):
            self.mode = 'oaipmh'
            self.request_version = '2.0.2'
            LOGGER.info('OAI-PMH mode detected; processing request.')
            self.oaiargs = dict((k, v) for k, v in self.kvp.items() if k)
            self.kvp = self.oaipmh().request(self.kvp)

        if self.request_version == '2.0.2':
            self.iface = csw2.Csw2(server_csw=self)
            self.context.set_model('csw')

        # configure transaction support, if specified in config
        self._gen_manager()

        namespaces = self.context.namespaces
        ops = self.context.model['operations']
        constraints = self.context.model['constraints']
        # generate domain model
        # NOTE: We should probably avoid this sort of mutable state for WSGI
        if 'GetDomain' not in ops:
            ops['GetDomain'] = self.context.gen_domains()

        # generate distributed search model, if specified in config
        if self.config.has_option('server', 'federatedcatalogues'):
            LOGGER.info('Configuring distributed search')

            constraints['FederatedCatalogues'] = {'values': []}

            for fedcat in self.config.get('server',
                                          'federatedcatalogues').split(','):
                LOGGER.debug('federated catalogue: %s', fedcat)
                constraints['FederatedCatalogues']['values'].append(fedcat)

        for key, value in self.outputschemas.items():
            get_records_params = ops['GetRecords']['parameters']
            get_records_params['outputSchema']['values'].append(
                value.NAMESPACE)
            get_records_by_id_params = ops['GetRecordById']['parameters']
            get_records_by_id_params['outputSchema']['values'].append(
                value.NAMESPACE)
            if 'Harvest' in ops:
                harvest_params = ops['Harvest']['parameters']
                harvest_params['ResourceType']['values'].append(
                    value.NAMESPACE)

        LOGGER.info('Setting MaxRecordDefault')
        if self.config.has_option('server', 'maxrecords'):
            constraints['MaxRecordDefault']['values'] = [
                self.config.get('server', 'maxrecords')]

        # load profiles
        if self.config.has_option('server', 'profiles'):
            self.profiles = pprofile.load_profiles(
                os.path.join('pycsw', 'plugins', 'profiles'),
                pprofile.Profile,
                self.config.get('server', 'profiles')
            )

            for prof in self.profiles['plugins'].keys():
                tmp = self.profiles['plugins'][prof](self.context.model,
                                                     namespaces,
                                                     self.context)

                key = tmp.outputschema  # to ref by outputschema
                self.profiles['loaded'][key] = tmp
                self.profiles['loaded'][key].extend_core(self.context.model,
                                                         namespaces,
                                                         self.config)

            LOGGER.debug('Profiles loaded: %s' % list(self.profiles['loaded'].keys()))

        # init repository
        # look for tablename, set 'records' as default
        if not self.config.has_option('repository', 'table'):
            self.config.set('repository', 'table', 'records')

        repo_filter = None
        if self.config.has_option('repository', 'filter'):
            repo_filter = self.config.get('repository', 'filter')

        if self.config.has_option('repository', 'source'):  # load custom repository
            rs = self.config.get('repository', 'source')
            rs_modname, rs_clsname = rs.rsplit('.', 1)

            rs_mod = __import__(rs_modname, globals(), locals(), [rs_clsname])
            rs_cls = getattr(rs_mod, rs_clsname)

            try:
                self.repository = rs_cls(self.context, repo_filter)
                LOGGER.debug('Custom repository %s loaded (%s)', rs, self.repository.dbtype)
            except Exception as err:
                msg = 'Could not load custom repository %s: %s' % (rs, err)
                LOGGER.exception(msg)
                error = 1
                code = 'NoApplicableCode'
                locator = 'service'
                text = 'Could not initialize repository. Check server logs'

        else:  # load default repository
            self.orm = 'sqlalchemy'
            from pycsw.core import repository
            try:
                LOGGER.info('Loading default repository')
                self.repository = repository.Repository(
                    self.config.get('repository', 'database'),
                    self.context,
                    self.environ.get('local.app_root', None),
                    self.config.get('repository', 'table'),
                    repo_filter
                )
                LOGGER.debug(
                    'Repository loaded (local): %s.' % self.repository.dbtype)
            except Exception as err:
                msg = 'Could not load repository (local): %s' % err
                LOGGER.exception(msg)
                error = 1
                code = 'NoApplicableCode'
                locator = 'service'
                text = 'Could not initialize repository. Check server logs'

        if self.requesttype == 'POST':
            LOGGER.debug('HTTP POST request')
            LOGGER.debug('CSW version: %s', self.iface.version)
            self.kvp = self.iface.parse_postdata(self.request)

        if isinstance(self.kvp, str):  # it's an exception
            error = 1
            locator = 'service'
            text = self.kvp
            if (self.kvp.find('the document is not valid') != -1 or
                    self.kvp.find('document not well-formed') != -1):
                code = 'NoApplicableCode'
            else:
                code = 'InvalidParameterValue'

        LOGGER.debug('HTTP Headers:\n%s.', self.environ)
        LOGGER.debug('Parsed request parameters: %s', self.kvp)

        if (not isinstance(self.kvp, str) and 'mode' in self.kvp and
                self.kvp['mode'] == 'opensearch'):
            self.mode = 'opensearch'
            LOGGER.info('OpenSearch mode detected; processing request.')
            self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if ((len(self.kvp) == 0 and self.request_version == '3.0.0') or
                (len(self.kvp) == 1 and 'config' in self.kvp)):
            LOGGER.info('Turning on default csw30:Capabilities for base URL')
            self.kvp = {
                'service': 'CSW',
                'acceptversions': '3.0.0',
                'request': 'GetCapabilities'
            }
            http_accept = self.environ.get('HTTP_ACCEPT', '')
            if 'application/opensearchdescription+xml' in http_accept:
                self.mode = 'opensearch'
                self.kvp['outputschema'] = 'http://www.w3.org/2005/Atom'

        if error == 0:
            # test for the basic keyword values (service, version, request)
            basic_options = ['service', 'request']
            request = self.kvp.get('request', '')
            own_version_integer = util.get_version_integer(
                self.request_version)
            if self.request_version == '2.0.2':
                basic_options.append('version')
            if self.request_version == '3.0.0' and 'version' not in self.kvp and self.requesttype == 'POST':
                if 'service' not in self.kvp:
                    self.kvp['service'] = 'CSW'
                    basic_options.append('service')
                self.kvp['version'] = self.request_version
                basic_options.append('version')

            for k in basic_options:
                if k not in self.kvp:
                    if (k in ['version', 'acceptversions'] and
                            request == 'GetCapabilities'):
                        pass
                    else:
                        error = 1
                        locator = k
                        code = 'MissingParameterValue'
                        text = 'Missing keyword: %s' % k
                        break

            # test each of the basic keyword values
            if error == 0:
                # test service
                if self.kvp['service'] != 'CSW':
                    error = 1
                    locator = 'service'
                    code = 'InvalidParameterValue'
                    text = 'Invalid value for service: %s.\
                    Value MUST be CSW' % self.kvp['service']

                # test version
                kvp_version = self.kvp.get('version', '')
                try:
                    kvp_version_integer = util.get_version_integer(kvp_version)
                except Exception as err:
                    kvp_version_integer = 'invalid_value'
                if (request != 'GetCapabilities' and
                        kvp_version_integer != own_version_integer):
                    error = 1
                    locator = 'version'
                    code = 'InvalidParameterValue'
                    text = ('Invalid value for version: %s. Value MUST be '
                            '2.0.2 or 3.0.0' % kvp_version)

                # check for GetCapabilities acceptversions
                if 'acceptversions' in self.kvp:
                    for vers in self.kvp['acceptversions'].split(','):
                        vers_integer = util.get_version_integer(vers)
                        if vers_integer == own_version_integer:
                            break
                        else:
                            error = 1
                            locator = 'acceptversions'
                            code = 'VersionNegotiationFailed'
                            text = ('Invalid parameter value in '
                                    'acceptversions: %s. Value MUST be '
                                    '2.0.2 or 3.0.0' %
                                    self.kvp['acceptversions'])

                # test request
                if self.kvp['request'] not in \
                    self.context.model['operations']:
                    error = 1
                    locator = 'request'
                    if request in ['Transaction', 'Harvest']:
                        code = 'OperationNotSupported'
                        text = '%s operations are not supported' % request
                    else:
                        code = 'InvalidParameterValue'
                        text = 'Invalid value for request: %s' % request

        if error == 1:  # return an ExceptionReport
            LOGGER.error('basic service options error: %s, %s, %s', code, locator, text)
            self.response = self.iface.exceptionreport(code, locator, text)

        else:  # process per the request value

            if 'responsehandler' in self.kvp:
                # set flag to process asynchronously
                import threading
                self.asynchronous = True
                request_id = self.kvp.get('requestid', None)
                if request_id is None:
                    import uuid
                    self.kvp['requestid'] = str(uuid.uuid4())

            if self.kvp['request'] == 'GetCapabilities':
                self.response = self.iface.getcapabilities()
            elif self.kvp['request'] == 'DescribeRecord':
                self.response = self.iface.describerecord()
            elif self.kvp['request'] == 'GetDomain':
                self.response = self.iface.getdomain()
            elif self.kvp['request'] == 'GetRecords':
                if self.asynchronous:  # process asynchronously
                    threading.Thread(target=self.iface.getrecords).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.getrecords()
            elif self.kvp['request'] == 'GetRecordById':
                self.response = self.iface.getrecordbyid()
            elif self.kvp['request'] == 'GetRepositoryItem':
                self.response = self.iface.getrepositoryitem()
            elif self.kvp['request'] == 'Transaction':
                self.response = self.iface.transaction()
            elif self.kvp['request'] == 'Harvest':
                if self.asynchronous:  # process asynchronously
                    threading.Thread(target=self.iface.harvest).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.harvest()
            else:
                self.response = self.iface.exceptionreport(
                    'InvalidParameterValue', 'request',
                    'Invalid request parameter: %s' % self.kvp['request']
                )

        LOGGER.info('Request processed')
        if self.mode == 'sru':
            LOGGER.info('SRU mode detected; processing response.')
            self.response = self.sru().response_csw2sru(self.response,
                                                        self.environ)
        elif self.mode == 'opensearch':
            LOGGER.info('OpenSearch mode detected; processing response.')
            self.response = self.opensearch().response_csw2opensearch(
                self.response, self.config)

        elif self.mode == 'oaipmh':
            LOGGER.info('OAI-PMH mode detected; processing response.')
            self.response = self.oaipmh().response(
                self.response, self.oaiargs, self.repository,
                self.config.get('server', 'url')
            )

        return self._write_response()
예제 #5
0
파일: server.py 프로젝트: SNIMar-WP4/pycsw
    def dispatch(self, writer=sys.stdout, write_headers=True):
        """ Handle incoming HTTP request """

        if self.requesttype == "GET":
            self.kvp = self.normalize_kvp(self.kvp)
            version_202 = "version" in self.kvp and self.kvp["version"] == "2.0.2"
            accept_version_202 = "acceptversions" in self.kvp and "2.0.2" in self.kvp["acceptversions"]
            if version_202 or accept_version_202:
                self.request_version = "2.0.2"
        elif self.requesttype == "POST":
            if self.request.find("2.0.2") != -1:
                self.request_version = "2.0.2"

        if not isinstance(self.kvp, str) and "mode" in self.kvp and self.kvp["mode"] == "sru":
            self.mode = "sru"
            self.request_version = "2.0.2"
            LOGGER.debug("SRU mode detected; processing request.")
            self.kvp = self.sru().request_sru2csw(self.kvp)

        if not isinstance(self.kvp, str) and "mode" in self.kvp and self.kvp["mode"] == "oaipmh":
            self.mode = "oaipmh"
            self.request_version = "2.0.2"
            LOGGER.debug("OAI-PMH mode detected; processing request.")
            self.oaiargs = dict((k, v) for k, v in self.kvp.items() if k)
            self.kvp = self.oaipmh().request(self.kvp)

        if self.request_version == "2.0.2":
            self.iface = csw2.Csw2(server_csw=self)
            self.context.set_model("csw")

        # configure transaction support, if specified in config
        self._gen_manager()

        namespaces = self.context.namespaces
        ops = self.context.model["operations"]
        constraints = self.context.model["constraints"]
        # generate domain model
        # NOTE: We should probably avoid this sort of mutable state for WSGI
        if "GetDomain" not in ops:
            ops["GetDomain"] = self.context.gen_domains()

        # generate distributed search model, if specified in config
        if self.config.has_option("server", "federatedcatalogues"):
            LOGGER.debug("Configuring distributed search.")
            constraints["FederatedCatalogues"] = {"values": []}

            for fedcat in self.config.get("server", "federatedcatalogues").split(","):
                constraints["FederatedCatalogues"]["values"].append(fedcat)

        for key, value in self.outputschemas.items():
            get_records_params = ops["GetRecords"]["parameters"]
            get_records_params["outputSchema"]["values"].append(value.NAMESPACE)
            get_records_by_id_params = ops["GetRecordById"]["parameters"]
            get_records_by_id_params["outputSchema"]["values"].append(value.NAMESPACE)
            if "Harvest" in ops:
                harvest_params = ops["Harvest"]["parameters"]
                harvest_params["ResourceType"]["values"].append(value.NAMESPACE)

        LOGGER.debug("Setting MaxRecordDefault")
        if self.config.has_option("server", "maxrecords"):
            constraints["MaxRecordDefault"]["values"] = [self.config.get("server", "maxrecords")]

        # load profiles
        if self.config.has_option("server", "profiles"):
            self.profiles = pprofile.load_profiles(
                os.path.join("pycsw", "plugins", "profiles"), pprofile.Profile, self.config.get("server", "profiles")
            )

            for prof in self.profiles["plugins"].keys():
                tmp = self.profiles["plugins"][prof](self.context.model, namespaces, self.context)

                key = tmp.outputschema  # to ref by outputschema
                self.profiles["loaded"][key] = tmp
                self.profiles["loaded"][key].extend_core(self.context.model, namespaces, self.config)

            LOGGER.debug("Profiles loaded: %s." % self.profiles["loaded"].keys())

        # init repository
        # look for tablename, set 'records' as default
        if not self.config.has_option("repository", "table"):
            self.config.set("repository", "table", "records")

        repo_filter = None
        if self.config.has_option("repository", "filter"):
            repo_filter = self.config.get("repository", "filter")

        if self.config.has_option("repository", "source") and self.config.get("repository", "source") == "geonode":

            # load geonode repository
            from pycsw.plugins.repository.geonode import geonode_

            try:
                self.repository = geonode_.GeoNodeRepository(self.context, repo_filter)
                LOGGER.debug("GeoNode repository loaded " "(geonode): %s." % self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                    "NoApplicableCode", "service", "Could not load repository (geonode): %s" % str(err)
                )

        elif self.config.has_option("repository", "source") and self.config.get("repository", "source") == "odc":

            # load odc repository
            from pycsw.plugins.repository.odc import odc

            try:
                self.repository = odc.OpenDataCatalogRepository(self.context, repo_filter)
                LOGGER.debug("OpenDataCatalog repository loaded " "(geonode): %s." % self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                    "NoApplicableCode", "service", "Could not load repository (odc): %s" % str(err)
                )

        else:  # load default repository
            self.orm = "sqlalchemy"
            from pycsw.core import repository

            try:
                self.repository = repository.Repository(
                    self.config.get("repository", "database"),
                    self.context,
                    self.environ.get("local.app_root", None),
                    self.config.get("repository", "table"),
                    repo_filter,
                )
                LOGGER.debug("Repository loaded (local): %s." % self.repository.dbtype)
            except Exception as err:
                self.response = self.iface.exceptionreport(
                    "NoApplicableCode", "service", "Could not load repository (local): %s" % str(err)
                )

        if self.requesttype == "POST":
            LOGGER.debug(self.iface.version)
            self.kvp = self.iface.parse_postdata(self.request)

        error = 0

        if isinstance(self.kvp, str):  # it's an exception
            error = 1
            locator = "service"
            text = self.kvp
            if self.kvp.find("the document is not valid") != -1 or self.kvp.find("document not well-formed") != -1:
                code = "NoApplicableCode"
            else:
                code = "InvalidParameterValue"

        LOGGER.debug("HTTP Headers:\n%s." % self.environ)
        LOGGER.debug("Parsed request parameters: %s" % self.kvp)

        if not isinstance(self.kvp, str) and "mode" in self.kvp and self.kvp["mode"] == "opensearch":
            self.mode = "opensearch"
            LOGGER.debug("OpenSearch mode detected; processing request.")
            self.kvp["outputschema"] = "http://www.w3.org/2005/Atom"

        if (self.kvp == {"": ""} and self.request_version == "3.0.0") or (len(self.kvp) == 1 and "config" in self.kvp):
            LOGGER.debug("Turning on default csw30:Capabilities for base URL")
            self.kvp = {"service": "CSW", "acceptversions": "3.0.0", "request": "GetCapabilities"}
            http_accept = self.environ.get("HTTP_ACCEPT", "")
            if "application/opensearchdescription+xml" in http_accept:
                self.mode = "opensearch"
                self.kvp["outputschema"] = "http://www.w3.org/2005/Atom"

        if error == 0:
            # test for the basic keyword values (service, version, request)
            basic_options = ["service", "request"]
            request = self.kvp.get("request", "")
            own_version_integer = util.get_version_integer(self.request_version)
            if self.request_version == "2.0.2":
                basic_options.append("version")

            for k in basic_options:
                if k not in self.kvp:
                    if k in ["version", "acceptversions"] and request == "GetCapabilities":
                        pass
                    else:
                        error = 1
                        locator = k
                        code = "MissingParameterValue"
                        text = "Missing keyword: %s" % k
                        break

            # test each of the basic keyword values
            if error == 0:
                # test service
                if self.kvp["service"] != "CSW":
                    error = 1
                    locator = "service"
                    code = "InvalidParameterValue"
                    text = (
                        "Invalid value for service: %s.\
                    Value MUST be CSW"
                        % self.kvp["service"]
                    )

                # test version
                kvp_version = self.kvp.get("version", "")
                kvp_version_integer = util.get_version_integer(kvp_version)
                if request != "GetCapabilities" and kvp_version_integer != own_version_integer:
                    error = 1
                    locator = "version"
                    code = "InvalidParameterValue"
                    text = "Invalid value for version: %s. Value MUST be " "2.0.2 or 3.0.0" % self.kvp["version"]

                # check for GetCapabilities acceptversions
                if "acceptversions" in self.kvp:
                    for vers in self.kvp["acceptversions"].split(","):
                        vers_integer = util.get_version_integer(vers)
                        if vers_integer == own_version_integer:
                            break
                        else:
                            error = 1
                            locator = "acceptversions"
                            code = "VersionNegotiationFailed"
                            text = (
                                "Invalid parameter value in "
                                "acceptversions: %s. Value MUST be "
                                "2.0.2 or 3.0.0" % self.kvp["acceptversions"]
                            )

                # test request
                if request not in ops.keys():
                    error = 1
                    locator = "request"
                    if request in ["Transaction", "Harvest"]:
                        code = "OperationNotSupported"
                        text = "%s operations are not supported" % request
                    else:
                        code = "InvalidParameterValue"
                        text = "Invalid value for request: %s" % request

        if error == 1:  # return an ExceptionReport
            self.response = self.iface.exceptionreport(code, locator, text)

        else:  # process per the request value

            if "responsehandler" in self.kvp:
                # set flag to process asynchronously
                import threading

                self.async = True
                request_id = self.kvp.get("requestid", None)
                if request_id is None:
                    import uuid

                    self.kvp["requestid"] = str(uuid.uuid4())

            if self.kvp["request"] == "GetCapabilities":
                self.response = self.iface.getcapabilities()
            elif self.kvp["request"] == "DescribeRecord":
                self.response = self.iface.describerecord()
            elif self.kvp["request"] == "GetDomain":
                self.response = self.iface.getdomain()
            elif self.kvp["request"] == "GetRecords":
                if self.async:  # process asynchronously
                    threading.Thread(target=self.iface.getrecords).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.getrecords()
            elif self.kvp["request"] == "GetRecordById":
                self.response = self.iface.getrecordbyid()
            elif self.kvp["request"] == "GetRepositoryItem":
                self.response = self.iface.getrepositoryitem()
            elif self.kvp["request"] == "Transaction":
                self.response = self.iface.transaction()
            elif self.kvp["request"] == "Harvest":
                if self.async:  # process asynchronously
                    threading.Thread(target=self.iface.harvest).start()
                    self.response = self.iface._write_acknowledgement()
                else:
                    self.response = self.iface.harvest()
            else:
                self.response = self.iface.exceptionreport(
                    "InvalidParameterValue", "request", "Invalid request parameter: %s" % self.kvp["request"]
                )

        if self.mode == "sru":
            LOGGER.debug("SRU mode detected; processing response.")
            self.response = self.sru().response_csw2sru(self.response, self.environ)
        elif self.mode == "opensearch":
            LOGGER.debug("OpenSearch mode detected; processing response.")
            self.response = self.opensearch().response_csw2opensearch(self.response, self.config)

        elif self.mode == "oaipmh":
            LOGGER.debug("OAI-PMH mode detected; processing response.")
            self.response = self.oaipmh().response(
                self.response, self.oaiargs, self.repository, self.config.get("server", "url")
            )

        return self._write_response()