diff --git a/stream.go b/stream.go index cfdb5bfb..b58f7f8d 100644 --- a/stream.go +++ b/stream.go @@ -663,3 +663,13 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) { } return nil } + +// MethodFromServerStream returns the method string for the input stream. +// The returned string is in the format of "/service/method". +func MethodFromServerStream(stream ServerStream) (string, bool) { + s, ok := transport.StreamFromContext(stream.Context()) + if !ok { + return "", ok + } + return s.Method(), ok +} diff --git a/test/end2end_test.go b/test/end2end_test.go index 6d59d298..a5e81a99 100644 --- a/test/end2end_test.go +++ b/test/end2end_test.go @@ -5552,3 +5552,23 @@ func testServiceConfigMaxMsgSizeTD(t *testing.T, e env) { t.Fatalf("%v.Send(%v) = %v, want _, error code: %s", stream, sreq, err, codes.ResourceExhausted) } } + +func TestMethodFromServerStream(t *testing.T) { + defer leakcheck.Check(t) + const testMethod = "/package.service/method" + e := tcpClearRREnv + te := newTest(t, e) + var method string + var ok bool + te.unknownHandler = func(srv interface{}, stream grpc.ServerStream) error { + method, ok = grpc.MethodFromServerStream(stream) + return nil + } + + te.startServer(nil) + defer te.tearDown() + _ = te.clientConn().Invoke(context.Background(), testMethod, nil, nil) + if !ok || method != testMethod { + t.Fatalf("Invoke with method %q, got %q, %v, want %q, true", testMethod, method, ok, testMethod) + } +}