Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metadata is empty, but Network tab shows it #1376

Open
EByrdS opened this issue Oct 18, 2023 · 2 comments
Open

Metadata is empty, but Network tab shows it #1376

EByrdS opened this issue Oct 18, 2023 · 2 comments

Comments

@EByrdS
Copy link

EByrdS commented Oct 18, 2023

In short, the metadata of my web-grpc client is always empty.

Proto definition

Let's say my proto file looks like:

// some/path/myservice.proto
syntax = "proto3";

import "google/protobuf/empty.proto";

package some.path.myservice;

service MyService {
  rpc RespondMetadata(google.protobuf.Empty) returns (google.protobuf.Empty) {}
}

Code generation

I generated code for my proto files using "grpc-web": "^1.4.2".

And protoc:

$ protoc --version
libprotoc 24.3

The command is:

protoc -I=. --js_out=import_style=commonjs,binary:. \
  --grpc-web_out=import_style=typescript,mode=grpcweb:. \
  some/path/myservice.proto

Server-side

The server of this gRPC sets the metadata header some-header in Golang:

func  (s myServer) RespondMetadata(ctx context.Context, request *emptypb.Empty) (*emptypb.Empty, error) {
	// ... Do some other stuff
        // All side-effects resulting from this call happen sucessfully in the server. e.g. printing to console

	// Set the metadata key value pair as header
	header := metadata.New(map[string]string{"some-header": "some-value"})
	err := grpc.SetHeader(ctx, header)
	if err != nil {
		return nil, fmt.Errorf("Failed to set header: %w", err)
	}

	return &emptypb.Empty{}, nil
}

I know this is working fine because I can create a Golang client for this server and successfully read the headers, both by dialing into the grpc port directly, or by dialing an Envoy proxy that I have already set up.

Metadata transformed into HTTP headers

If I create my grpc client for the browser using grpc-web, I can see the metadata present in the HTTP Response Headers of the browser Network tab:

image

Issue within browser (grpc-web) typescript code

However, in the code the metadata is always empty.

I initialize my client in the following way:

import { MyServiceClient } "some/path/MyServiceClientPb";

const client = new MyServiceClient(serverUrl, null, null)

And I have tried calling the method and reading metadata in the following ways:

      const grpcRequest = new google_protobuf_empty_pb.Empty();

      const call = client.respondMetadata(grpcRequest, {}, (err, response) => {
        if (err) {
          console.log("There was an error", err);
        } else {
          // response is of type google.protobuf.Empty
          // So I can't read metadata from here
          console.log("Successfull response: ", response) 
        }
      });

      call.on('status', (status) => {
        console.log("Status metadata: ", status.metadata) // This is empty: {}
        console.log("Status!:", status)
      });
      call.on('metadata', (metadata) => {
        console.log("Received metadata: ", metadata); // This is empty: {}
        const value = metadata['some-header'];

        console.log('The received header is: ', value); // this is undefined
      })

Any ideas how can I read response metadata? Or why are these approaches not working?

@sampajano
Copy link
Collaborator

Hi! Thanks for reporting!

I'm not really familiar with the go grpc server, and how metadata is propagated, but we do have a demo with a Node server which echos the metadata and prints it out.

You can run it using:

docker-compose up --build node-server envoy ts-client

And you can see the metadata being printed out in the console, with the following code:

call.on('status', (status: grpcWeb.Status) => {
if (status.metadata) {
console.log('Received metadata');
console.log(status.metadata);
}
});

Could you try the above example, and then compare the base64 decoded payload of what you got on your setup v.s. the demo?

It should help understand where the discrepancies are.

Thanks :)

@vdhanan
Copy link

vdhanan commented Jan 29, 2024

hey @EByrdS did you ever figure this out? i'm running into the same issue...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants