У меня есть приложение Spring GraphQL, которое вызывает другой внутренний микросервис с использованием протокола gRPC. Мне нужно установить токен носителя и другую информацию в заголовок gRPC, я думаю, мы можем настроить его с помощью перехватчика gRPC (реализация ClientInterceptor
).
Я попробовал следующий подход:
На основе Как получить доступ к атрибутам из grpc Context.current()? Я создал ключ, чтобы мы могли ссылаться на него в spring-service и перехватчике
public class ContextKeyHolder {
public static Context.Key<String> USER_INFO = Context.key("USER");
public static Context.Key<String> BEARER = Context.key("BEARER");
}
// spring-service method
public Employee getEmployee() {
...
Context.current().withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername());
Context.current().withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken());
return grpcClient.getEmployee(...);
}
// interceptCall implementation
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor,
CallOptions callOptions, Channel channel) {
return new ForwardingClientCall.SimpleForwardingClientCall<>(
channel.newCall(methodDescriptor, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
...
String userInfo = ContextKeyHolder.USER_INFO.get(Context.current());
System.out.println("user => " + userInfo);
...
super.start(responseListener, headers);
}
};
}
Здесь я получаю null
userInfo в методе перехватчика. я что-то пропустил здесь?
Другой вариант - использовать ThreadLocal для хранения контекста, но я не уверен, что это правильный выбор.
Созданный вами контекст необходимо использовать при совершении вызова. Итак, ваш код должен быть:
return Context.current()
.withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
.withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken())
.call(() -> { return grpcClient.getEmployee(...);});
В качестве альтернативы:
Context oldContext =
Context.current()
.withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
.withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken())
.attach();
Employee valueToReturn = grpcClient.getEmployee(...);
Context.current().detach(oldContext);
return valueToReturn;