Interceptors of dart Grpc

Issue

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);
  }
}

Answered By – Dukhanov Maxim

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.