grpc-dart
grpc-dart copied to clipboard
Async client interceptors?
I would like to perform an async operation within an interceptor. The problem is it has to return a ResponseFuture
, not a Future
, so I cannot mark the interceptUnary
method as async and perform asynchronous code within it (like access the platform method channel).
Is there a way to work around this to perform async operations within the interceptor?
3.0.2
Repro steps
@override
ResponseFuture<R> interceptUnary<Q, R>(
ClientMethod<Q, R> method,
Q request,
CallOptions options,
ClientUnaryInvoker<Q, R> invoker,
) async { } // error
There are many issues and pull requests for this. Waiting https://github.com/grpc/grpc-dart/pull/489 to be merged.
Any Solution?
Any update/workaround?
@EnesKaraosman you should probably use this code as a solution
@EnesKaraosman you should probably use this code as a solution
Tried this one but received syntax issues with dart 2.18.4
Tried this one but received syntax issues with dart 2.18.4
Well, you most likely can fix them. The code should still work but needs to be updated.
Hi thanks for this solutions, but how I can return an custom error in the interceptor?
@lazicah You can rethrow
them and handle via your Controller
/Bloc
etc... If you are talking about really return
ing, you can't and shouldn't.
@mraleph it is very useful to have Async interceptStreaming
as well.
For example we want retrive Firebase Token in the interceptor - it will affect interceptStreaming
and interceptUnary
Ideally:
@override
Stream<R> interceptStreaming<Q, R>(
ClientMethod<Q, R> method,
Stream<Q> requests,
CallOptions options,
ClientStreamingInvoker<Q, R> invoker,
) async* {
final token = await _getToken?.call();
yield* invoker(method, requests, options.withToken(token));
}
@override
FutureOr<R> interceptUnary<Q, R>(
ClientMethod<Q, R> method,
Q request,
CallOptions options,
ClientUnaryInvoker<Q, R> invoker,
) async {
final token = await _getToken?.call();
return invoker(method, request, options.withToken(token));
}
Came here looking for exactly the same need as @zs-dima . I would love to be able to just await
in the intercept* methods. I've been trying to rework the workaround "retry" solution from @mraleph but I'm getting confused with the multiple layers of completers and futures.
After a lot of experimentation and nearly modifying the package for my own needs, I discovered metadataProviders
which does exactly what I needed to modify the call options metadata before the request is made. I remember reading that field a while ago, but somehow ignored it, thinking an interceptor is what I really needed.
It turned out to be very simple:
@override
ResponseFuture<R> interceptUnary<Q, R>(
ClientMethod<Q, R> method,
Q request,
CallOptions options,
ClientUnaryInvoker<Q, R> invoker,
) {
addToken(Map<String, String> metadata, String _) async {
final token = await FirebaseAuth.instance.currentUser?.getIdToken();
metadata['auth'] = token ?? '';
}
return invoker(
method,
request,
options.mergedWith(CallOptions(providers: [addToken])),
);
}