Я использую декораторы для аутентификации. Если это удастся, я хочу расширить context
с дополнительной информацией. Как это может быть достигнуто?
@require_authorization
def test(request, context):
<...>
def require_authorization(func):
def wrapper(request, context):
<...How can I extend the context here?...>
return func(request, context)
return wrapper
Я также попробовал ServiceInterceptor, но тоже застрял в этом маршруте:
class Interceptor(grpc.ServerInterceptor):
def intercept_service(self, continuation, handler_call_details):
<...Can I extend the metadata here somehow?...>
return continuation(handler_call_details)
server = grpc.server(
futures.ThreadPoolExecutor(max_workers=10),
interceptors=(Interceptor(),),
)
Обходной путь с декоратором
На основании ответа Лиди Чжэн (спасибо!) Я использую следующий декоратор. Вероятно, наиболее раздражающим аспектом является предоставление реализаций для всех методов абстрактного базового класса. Поскольку это плохо документировано, я получил их от источника.
class AuthServicerContext(grpc.ServicerContext):
def __init__(self, context: grpc.ServicerContext, func_name):
self._original_context = context
meta = dict(context.invocation_metadata())
def abort(self, code, details):
self._original_context.abort(code, details)
def abort_with_status(self, status):
self._original_context.abort_with_status(status)
def add_callback(self, callback):
self._original_context.add_callback(callback)
def auth_context(self):
self._original_context.auth_context()
def cancel(self):
self._original_context.cancel()
def invocation_metadata(self):
self._original_context.invocation_metadata()
def is_active(self):
self._original_context.is_active()
def peer(self):
self._original_context.peer()
def peer_identities(self):
self._original_context.peer_identities()
def peer_identity_key(self):
self._original_context.peer_identity_key()
def send_initial_metadata(self, initial_metadata):
self._original_context.send_initial_metadata(initial_metadata)
def set_code(self,code):
self._original_context.set_code(code)
def set_details(self, details):
self._original_context.set_details(details)
def set_trailing_metadata(self, trailing_metadata):
self._original_context.abort(trailing_metadata)
def time_remaining(self):
self._original_context.time_remaining()
def require_authorization(func):
def wrapper(self, request, context):
return func(self, request, AuthServicerContext(context, func.__name__))
return wrapper