Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 51 additions & 10 deletions magpie/adapter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import functools
import inspect
import re
import warnings
Expand Down Expand Up @@ -116,10 +117,13 @@
JSON,
AnyResponseType,
AnySettingsContainer,
Callable,
Iterable,
ServiceConfigItem,
ServiceHookConfigItem,
ServiceHookType,
Str
Str,
Tuple,
)

from twitcher.models.service import ServiceConfig # noqa # pylint: disable=E0611 # Twitcher >= 0.6.3
Expand Down Expand Up @@ -302,11 +306,10 @@ def configurator_factory(self, container): # noqa: R0201

return config

def _apply_hooks(self, instance, service_name, hook_type, method, path, query):
# type: (Union[Request, Response], Str, ServiceHookType, Str, Str, Str) -> Union[Request, Response]
"""
Executes the hooks processing chain.
"""
def _discover_hooks(self, instance, service_name, hook_type, method, path, query):
# type: (Union[Request, Response], Str, ServiceHookType, Str, Str, Str, bool) -> Iterable[Tuple[Callable, Str, Str]]
"""Yields hook functions."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the multiline docstring.
Same for others.


svc_config = self.settings.get("magpie.services", {}).get(service_name, {})
svc_hooks = svc_config.get("hooks", [])
# copy to avoid (un)intentional modifications to configurations
Expand Down Expand Up @@ -338,14 +341,34 @@ def _apply_hooks(self, instance, service_name, hook_type, method, path, query):
for key, val in [("service", svc_config), ("hook", hook), ("context", ctx)]:
if key in signature.parameters:
kwargs[key] = val
yield functools.partial(hook_target, **kwargs), hook_qs, hook_cfg["target"]

def _apply_proxy_hooks(self, instance, service_name, hook_type, method, path, query):
# type: (Union[Request, Response], Str, ServiceHookType, Str, Str, Str, bool) -> Union[Request, Response]
"""Executes the hooks processing chain for request and response hooks."""
for hook_target, hook_qs, target in self._discover_hooks(instance, service_name, hook_type, method, path, query):
try:
instance = hook_target(instance, **kwargs)
instance = hook_target(instance)
except Exception as exc:
LOGGER.error("Hook failed %s (%s %s%s) [%s]",
hook_type, method, path, hook_qs, hook_cfg["target"], exc_info=exc)
hook_type, method, path, hook_qs, target, exc_info=exc)
raise exc
return instance

def _apply_verify_hooks(self, instance, service_name, hook_type, method, path, query):
# type: (Union[Request, Response], Str, ServiceHookType, Str, Str, Str, bool) -> bool
"""Executes the hooks processing chain for verify hooks."""
for hook_target, hook_qs, target in self._discover_hooks(instance, service_name, hook_type, method, path, query):
try:
verified = hook_target(instance)
except Exception as exc:
LOGGER.error("Hook failed %s (%s %s%s) [%s]",
hook_type, method, path, hook_qs, target, exc_info=exc)
raise exc
if not verified:
return False
return True

@staticmethod
def _proxied_service_path(request):
# type: (Request) -> Str
Expand Down Expand Up @@ -373,7 +396,7 @@ def request_hook(self, request, service):
This method can modified those members to adapt the request for specific service logic.
"""
request_path = self._proxied_service_path(request)
request = self._apply_hooks(
request = self._apply_proxy_hooks(
request, service["name"], "request",
request.method, request_path, request.query_string
)
Expand All @@ -391,12 +414,30 @@ def response_hook(self, response, service):
This method can modify the response to adapt it for specific service logic.
"""
request_path = self._proxied_service_path(response.request)
response = self._apply_hooks(
response = self._apply_proxy_hooks(
response, service["name"], "response",
response.request.method, request_path, response.request.query_string
)
return response

def verify_hook(self, request, service):
# type: (Request, ServiceConfig) -> bool
"""
Apply hook that can apply additional logic used to verify whether a request should be rejected.

.. versionadded:: 5.0.3
Requires ``Twitcher >= 0.11.2``.
Comment on lines +428 to +429

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

magpie 5.2.0
twitcher 0.12.0


Return False to indicate that the verify endpoint should return a "forbidden"
response regardless of whether the request is verified.
"""

request_path = self._proxied_service_path(request)
return self._apply_verify_hooks(
request, service["name"], "verify",
request.method, request_path, request.query_string, fail_fast=True
)

def send_request(self, request, service):
# type: (Request, ServiceConfig) -> Response
"""
Expand Down
Loading