forked from hans/Nominatim
configurable error formatting and content type in result formatter
This commit is contained in:
@@ -12,8 +12,11 @@ from collections import defaultdict
|
||||
from pathlib import Path
|
||||
import importlib
|
||||
|
||||
from .server.content_types import CONTENT_JSON
|
||||
|
||||
T = TypeVar('T') # pylint: disable=invalid-name
|
||||
FormatFunc = Callable[[T, Mapping[str, Any]], str]
|
||||
ErrorFormatFunc = Callable[[str, str, int], str]
|
||||
|
||||
|
||||
class FormatDispatcher:
|
||||
@@ -21,7 +24,11 @@ class FormatDispatcher:
|
||||
a module using decorators.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
def __init__(self, content_types: Optional[Mapping[str, str]] = None) -> None:
|
||||
self.error_handler: ErrorFormatFunc = lambda ct, msg, status: f"ERROR {status}: {msg}"
|
||||
self.content_types: Dict[str, str] = {}
|
||||
if content_types:
|
||||
self.content_types.update(content_types)
|
||||
self.format_functions: Dict[Type[Any], Dict[str, FormatFunc[Any]]] = defaultdict(dict)
|
||||
|
||||
|
||||
@@ -37,6 +44,15 @@ class FormatDispatcher:
|
||||
return decorator
|
||||
|
||||
|
||||
def error_format_func(self, func: ErrorFormatFunc) -> ErrorFormatFunc:
|
||||
""" Decorator for a function that formats error messges.
|
||||
There is only one error formatter per dispatcher. Using
|
||||
the decorator repeatedly will overwrite previous functions.
|
||||
"""
|
||||
self.error_handler = func
|
||||
return func
|
||||
|
||||
|
||||
def list_formats(self, result_type: Type[Any]) -> List[str]:
|
||||
""" Return a list of formats supported by this formatter.
|
||||
"""
|
||||
@@ -58,6 +74,32 @@ class FormatDispatcher:
|
||||
return self.format_functions[type(result)][fmt](result, options)
|
||||
|
||||
|
||||
def format_error(self, content_type: str, msg: str, status: int) -> str:
|
||||
""" Convert the given error message into a response string
|
||||
taking the requested content_type into account.
|
||||
|
||||
Change the format using the error_format_func decorator.
|
||||
"""
|
||||
return self.error_handler(content_type, msg, status)
|
||||
|
||||
|
||||
def set_content_type(self, fmt: str, content_type: str) -> None:
|
||||
""" Set the content type for the given format. This is the string
|
||||
that will be returned in the Content-Type header of the HTML
|
||||
response, when the given format is choosen.
|
||||
"""
|
||||
self.content_types[fmt] = content_type
|
||||
|
||||
|
||||
def get_content_type(self, fmt: str) -> str:
|
||||
""" Return the content type for the given format.
|
||||
|
||||
If no explicit content type has been defined, then
|
||||
JSON format is assumed.
|
||||
"""
|
||||
return self.content_types.get(fmt, CONTENT_JSON)
|
||||
|
||||
|
||||
def load_format_dispatcher(api_name: str, project_dir: Optional[Path]) -> FormatDispatcher:
|
||||
""" Load the dispatcher for the given API.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user