Skip to content

Metadata is empty, but Network tab shows it #1376

Open
@EByrdS

Description

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?

Activity

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

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions