Search code examples
flutterdartgrpcgrpc-dart

Interceptors of dart Grpc


I'm developing a flutter app using Grpc to connect to the server. Some of the services need extra metadata for authentication, so the first thing that comes to my mind is implementing an interceptor to add the metadata to those requests like this:

class MyClientInterceptor implements ClientInterceptor {

  @override
  ResponseFuture<R> interceptUnary<Q, R>(ClientMethod<Q, R> method, Q request, CallOptions options, invoker) {

    var newOptions = CallOptions.from([options])
      ..metadata.putIfAbsent('token', () => 'Some-Token');
    return invoker(method, request, newOptions);
  }
}

But I get Caught error: Unsupported operation: Cannot modify unmodifiable map because CallOptions uses an unmodifiable map.

First question: What is the best practice to add authentication to some of the requests instead of creating the Client stub with those metadata?

Second: How can I copy the metadata from options, modify it and use the modified object?


Solution

  • First question: What is the best practice to add authentication to some of the requests instead of creating the Client stub with those metadata?

    Some AUTH libs which I saw use metadata to provide authentication token/key etc. For example https://github.com/grpc/grpc-dart/blob/master/lib/src/auth/auth.dart#L43

    So do not hesitate to add your custom auth header in metadata dict. In can be done via interceptor as you did or via CallOptions:

    final resp = await _grpcClient.someApiCall(req,
              options: CallOptions(metadata: {'auth': 'your token'}));
    

    Second: How can I copy the metadata from options, modify it and use the modified object? Just clone previous CallOptions with new value via mergedWith

    Second question:

    
    class MyClientInterceptor implements ClientInterceptor {
    
      @override
      ResponseFuture<R> interceptUnary<Q, R>(ClientMethod<Q, R> method, Q request, CallOptions options, invoker) {
    
        var newOptions = options.mergedWith(
           CallOptions(
            metadata: <String, String>{
              'token': 'Some-Token',
            }
           )
        );
          
        return invoker(method, request, newOptions);
      }
    }