Source code for clarin.sru.server.wsgi
import logging
import typing
from typing import Dict
from typing import Iterable
from typing import Optional
from typing import Type
from typing import Union
from werkzeug import Request
from werkzeug import Response
from clarin.sru.constants import SRUVersion
from clarin.sru.exception import SRUConfigException
from clarin.sru.queryparser import SRUQueryParserRegistry
from clarin.sru.server.auth import SRUAuthenticationInfoProvider
from clarin.sru.server.auth import SRUAuthenticationInfoProviderFactory
from clarin.sru.server.config import SRUServerConfig
from clarin.sru.server.config import SRUServerConfigKey
from clarin.sru.server.server import SRUSearchEngine
from clarin.sru.server.server import SRUServer
if typing.TYPE_CHECKING:
# import typing_extensions as te
# wsgiref.types # only 3.11
# from _typeshed.wsgi import WSGIApplication
from _typeshed.wsgi import StartResponse
from _typeshed.wsgi import WSGIEnvironment
LOGGER = logging.getLogger(__name__)
# ---------------------------------------------------------------------------
[docs]class SRUServerApp: # WSGIApplication
def __init__(
self,
SRUSearchEngine_clazz: Union[Type[SRUSearchEngine], SRUSearchEngine],
config_file: str,
params: Dict[Union[SRUServerConfigKey, str], str],
develop: bool = False,
):
self.SRUSearchEngine_clazz = SRUSearchEngine_clazz
self.config_file = config_file
self.params = dict(params)
self.develop = develop
self.init()
# ----------------------------------------------------
[docs] def set_default_params(self) -> None:
# set defaults
if self.develop:
LOGGER.warning("Using >develop< mode!")
def _set_default(name, value):
if name not in self.params:
self.params[name] = value
LOGGER.warning(
"Using default '%s' for parameter '%s'"
", because it was not defined in configuration",
value,
name,
)
LOGGER.warning("THIS IS NOT RECOMMENDED FOR PRODUCTION DEPLOYMENT!")
_set_default(SRUServerConfigKey.SRU_TRANSPORT, "http")
_set_default(SRUServerConfigKey.SRU_HOST, "127.0.0.1")
_set_default(SRUServerConfigKey.SRU_PORT, "8080")
_set_default(SRUServerConfigKey.SRU_DATABASE, "/")
# allowed indented responses
self.params.setdefault(
SRUServerConfigKey.SRU_ALLOW_OVERRIDE_INDENT_RESPONSE, "true"
)
# set to SRU 2.0 version
self.params.setdefault(
SRUServerConfigKey.SRU_SUPPORTED_VERSION_DEFAULT, SRUVersion.VERSION_2_0
)
self.params.setdefault(
SRUServerConfigKey.SRU_SUPPORTED_VERSION_MAX, SRUVersion.VERSION_2_0
)
[docs] def init(self) -> None:
# Set some defaults (aka "plug and play" for development deployment)
# Override those for a production deployment through the params parameter
self.set_default_params()
# now go ahead and setup everything ...
try:
# parse SRU server configuration
config = SRUServerConfig.parse(self.params, self.config_file)
# create an instance of the search engine ...
LOGGER.debug(
"Creating new search engine from class %s", self.SRUSearchEngine_clazz
)
# TODO: create from package.class name (str) ?
try:
if not self.SRUSearchEngine_clazz:
raise TypeError("SRUSearchEngine_clazz is None")
# check that of class type and correct class
if isinstance(self.SRUSearchEngine_clazz, type):
if SRUSearchEngine not in self.SRUSearchEngine_clazz.mro():
raise ValueError(
"Parameter 'SRUSearchEngine_clazz' not of type SRUSearchEngine"
)
self.search_engine = self.SRUSearchEngine_clazz()
else:
if not isinstance(self.SRUSearchEngine_clazz, SRUSearchEngine):
raise ValueError(
"Invalid value for 'SRUSearchEngine_clazz' argument."
)
# got instance of class instead of type
self.search_engine = self.SRUSearchEngine_clazz
except Exception as ex:
raise SRUConfigException("Error creating search engine") from ex
# initialize search engine ...
qpr_builder = SRUQueryParserRegistry.Builder()
self.search_engine.init(config, qpr_builder, self.params)
# create authentication provider
auth_provider: Optional[SRUAuthenticationInfoProvider] = None
if isinstance(self.search_engine, SRUAuthenticationInfoProviderFactory):
LOGGER.debug("Creating new authentication info provider")
auth_provider = self.search_engine.create_SRUAuthenticationInfoProvider(
self.params
)
# finally create the sru server ...
self.server = SRUServer(
config=config,
query_parsers=qpr_builder.build(),
search_engine=self.search_engine,
authentication_info_provider=auth_provider,
)
except SRUConfigException as ex:
raise RuntimeError(
f"error configuring or inializing the server: {str(ex)}"
) from ex
[docs] def destroy(self) -> None:
"""Destroy the SRU server application"""
if self.search_engine:
self.search_engine.destroy()
# ----------------------------------------------------
[docs] def wsgi_app(
self, environ: "WSGIEnvironment", start_response: "StartResponse"
) -> Iterable[bytes]:
request = Request(environ)
response = Response()
self.server.handle_request(request, response)
return response(environ, start_response)
def __call__(
self, environ: "WSGIEnvironment", start_response: "StartResponse"
) -> Iterable[bytes]:
return self.wsgi_app(environ, start_response)
# ---------------------------------------------------------------------------