Go-micro: grpc client error " Unsupported Content-Type: application/grpc+proto", look like bug

Created on 29 Jul 2019  Â·  6Comments  Â·  Source: asim/go-micro

I use grpc server as micro server, httpbroker as broker, when I try publish a message, but some error occurs: {"id":"go.micro.client","code":500,"detail":"Unsupported Content-Type: application/grpc+proto","status":"Internal Server Error"}

mycode:

func main() {
    reg := etcdv3.NewRegistry(func(op *registry.Options) {
        op.Addrs = []string{
            "http://127.0.0.1:2379",
        }
    })

    service := micro.NewService(
        micro.Server(grpc.NewServer()),
        micro.Client(grpc.NewClient()),
        micro.Name("HelloGreeter1"),
        micro.Registry(reg),
    )

    service.Init()
    ctx := context.Background()
    cmsg := "message :  Hello World"
    err = service.Client().Publish(ctx, service.Client().NewMessage("testTopic", cmsg))
    if err != nil {
        fmt.Println(err.Error())
    }

    // blocking, cmsg can be sent, because Publish method is async
    select {
    }
}

debug find:
/client/grpc/grpc.go 489line

func (g *grpcClient) Publish(ctx context.Context, p client.Message, opts ...client.PublishOption) error {
    md, ok := metadata.FromContext(ctx)
    if !ok {
        md = make(map[string]string)
    }
    md["Content-Type"] = p.ContentType()

    cf, err := g.newCodec(p.ContentType()) // here
}

/client/grpc/grpc.go 262line

func (g *grpcClient) newCodec(contentType string) (codec.NewCodec, error) {
    if c, ok := g.opts.Codecs[contentType]; ok {
        return c, nil
    }

       // here,  I think should use defaultGRPCCodecs
    if cf, ok := defaultRPCCodecs[contentType]; ok {
        return cf, nil
    }
    return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType)
}
question

Most helpful comment

In version 1.8, the method NewMessage uses the variable "ContentType" to default to the client's "ContentType" support override but does not pass an overrideable parameter when calling NewMessage in the Publish method. "ContentType" can only use the client's "ContentType". The problem has occurred.

The method NewMessage in version 1.5 uses a fixed "ContentType" value of "application/octet-stream"

func (p *publisher) Publish(ctx context.Context, msg interface{}, opts ...client.PublishOption) error {
    return p.c.Publish(ctx, p.c.NewMessage(p.topic, msg), opts...)
}

go-micro/client/grpc/grpc.go

func (g *grpcClient) NewMessage(topic string, msg interface{}, opts ...client.MessageOption) client.Message {
    return newGRPCEvent(topic, msg, g.opts.ContentType, opts...)
}

The solution directly calls the Publish method in the client to solve this problem by specifying a specific "ContentType" with the third parameter.
go-micro/publisher.go

ev := &proto.Event{
   Id:        uuid.NewUUID().String(),
   Timestamp: time.Now().Unix(),
   Message:   fmt.Sprintf("Messaging you all day on %s", "example.topic.pubsub.1"),
}
_ = service.Client().Publish(context.Background(), service.Client().NewMessage("example.topic.pubsub.1", ev, func(options *client.MessageOptions) {options.ContentType = "application/octet-stream"}))

All 6 comments

I had the same problem, is this bug?

me too. that problem how to solve?

In version 1.8, the method NewMessage uses the variable "ContentType" to default to the client's "ContentType" support override but does not pass an overrideable parameter when calling NewMessage in the Publish method. "ContentType" can only use the client's "ContentType". The problem has occurred.

The method NewMessage in version 1.5 uses a fixed "ContentType" value of "application/octet-stream"

func (p *publisher) Publish(ctx context.Context, msg interface{}, opts ...client.PublishOption) error {
    return p.c.Publish(ctx, p.c.NewMessage(p.topic, msg), opts...)
}

go-micro/client/grpc/grpc.go

func (g *grpcClient) NewMessage(topic string, msg interface{}, opts ...client.MessageOption) client.Message {
    return newGRPCEvent(topic, msg, g.opts.ContentType, opts...)
}

The solution directly calls the Publish method in the client to solve this problem by specifying a specific "ContentType" with the third parameter.
go-micro/publisher.go

ev := &proto.Event{
   Id:        uuid.NewUUID().String(),
   Timestamp: time.Now().Unix(),
   Message:   fmt.Sprintf("Messaging you all day on %s", "example.topic.pubsub.1"),
}
_ = service.Client().Publish(context.Background(), service.Client().NewMessage("example.topic.pubsub.1", ev, func(options *client.MessageOptions) {options.ContentType = "application/octet-stream"}))

me too.

This is the appropriate fix https://github.com/micro/go-micro/pull/679

Now merged.

Was this page helpful?
0 / 5 - 0 ratings