2

I'm trying to send a metadata from the server side gprc using NestJS framework. On the official NestJS guide here: it shows a example of doing the server side grpc metadata:

@Controller()
export class HeroesService {
    @GrpcMethod()
    findOne(data: HeroById, metadata: Metadata, call: ServerUnaryCall<any>): Hero {
        const serverMetadata = new Metadata();
        const items = [
          { id: 1, name: 'John' },
          { id: 2, name: 'Doe' },
        ];
    
        serverMetadata.add('Set-Cookie', 'yummy_cookie=choco');
        call.sendMetadata(serverMetadata);
    
        return items.find(({ id }) => id === data.id);
    }
}

On my code, I wrote a similar code:

@GrpcMethod('ClinicService', 'GetCustomerClinicNames')
async GetCustomerClinicNames_GRPC(data: CustomerClinicID, call:ServerUnaryCall<Any,Any>) {
    const metadata = new Metadata();
    const result = await this.clinicService.GetClinicName(Number(data.customer_id));
    console.log(result);
    metadata.add('context', "Jello")
    call.sendMetadata(metadata)
    return { response: result};
}

However, it gives me an error says:

[Nest] 53188  - 04/06/2022, 5:17:50 PM   ERROR [RpcExceptionsHandler] call.sendMetadata is not a function
TypeError: call.sendMetadata is not a function
    at ClinicController.GetCustomerClinicNames_GRPC (C:\Users\Vibrant\Desktop\core-samples\src\clinic\clinic.controller.ts:118:10)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at C:\Users\Vibrant\Desktop\core-samples\node_modules\@nestjs\microservices\context\rpc-proxy.js:11:32

But I think the .sendMetadata is indeed a function. Where am I wrong about this?

For the sendMetadata Function, it is defined as:

export declare type ServerSurfaceCall = {
    cancelled: boolean;
    readonly metadata: Metadata;
    getPeer(): string;
    sendMetadata(responseMetadata: Metadata): void;
    getDeadline(): Deadline;
} & EventEmitter;

export declare type ServerUnaryCall<RequestType, ResponseType> = ServerSurfaceCall & {
    request: RequestType;
};
Clément Jean
  • 1,735
  • 1
  • 14
  • 32
Zichzheng
  • 1,090
  • 7
  • 25
  • I cannot reproduce your error, how do you generate your ts code from a proto file ? Dynamically, by loading a file like in the tutorial ? – Clément Jean Apr 07 '22 at 00:53
  • 1
    @ClémentJean Just edited, I think the the `ServerUnaryCall` is extend the `ServerSurfaceCall` I think this is the right type. I used the `ServerUnaryCall` in my code. – Zichzheng Apr 07 '22 at 00:54
  • @ClémentJean I added the proto files as a NestJS microservice. I just use the raw proto files. If I comment out the `call.sendMetadata(metadata)`, the grpc method will work as expected. – Zichzheng Apr 07 '22 at 01:03

1 Answers1

1

So apparently you need to keep the metadata parameter in your async GetCustomerClinicNames_GRPC. I tried with and without and it only worked when I had it.

so for example, I tried:

@GrpcMethod('HeroesService', 'FindOne')
findOne(data: any, call: ServerUnaryCall<any, any>): any

and that didn't work, then I tried:

@GrpcMethod('HeroesService', 'FindOne')
findOne(data: any, _metadata: Metadata, call: ServerUnaryCall<any, any>): any

and it worked by doing something like:

@GrpcMethod('HeroesService', 'FindOne')
findOne(data: any, _metadata: Metadata, call: ServerUnaryCall<any, any>): any {
    const items = [
        { id: 1, name: 'John' },
        { id: 2, name: 'Doe' },
    ];
    
    const metadata = new Metadata();
    metadata.add('context', 'Jello');
    call.sendMetadata(metadata);

    return items.find(({ id }) => id === data.id);
}

I'm not sure why though, since we are using named arguments.

Clément Jean
  • 1,735
  • 1
  • 14
  • 32
  • Thanks for the answer! This is helpful, after I added the metadata as an input parameter, the function works and the response is correct. However, the metadata I received is still empty. Does your metadata show up as expected? – Zichzheng Apr 07 '22 at 02:05
  • Yes it does show as expected, I tried with [evans CLI](https://github.com/ktr0731/evans) and the --enrich option. You could also try with the [Postman canary](https://www.postman.com/downloads/canary/) (they support gRPC now), just to make sure if your client code is the problem. – Clément Jean Apr 07 '22 at 02:07
  • Thanks for the info. Guess my client is working as expected. I have selected your answer as the answer to the question. Thanks! – Zichzheng Apr 07 '22 at 02:12