Files
x/sd/plugin/grpc.go
T
ginuerzh 18f39f940b fix(sd): add nil service guards, improve error messages, remove unused logger
- Add nil service guards to Register/Deregister/Renew in gRPC and HTTP
  plugins to prevent nil pointer dereferences
- Remove unused log field from grpcPlugin and httpPlugin
- Prefix HTTP error messages with operation context (sd register/deregister/renew/get)
- Return gRPC Register error directly instead of logging + returning
- Add 33 unit tests covering all operations, nil guards, and error paths
2026-05-25 23:04:27 +08:00

131 lines
2.6 KiB
Go

package sd
import (
"context"
"io"
"github.com/go-gost/core/sd"
"github.com/go-gost/plugin/sd/proto"
"github.com/go-gost/x/internal/plugin"
"google.golang.org/grpc"
)
type grpcPlugin struct {
conn grpc.ClientConnInterface
client proto.SDClient
}
// NewGRPCPlugin creates an SD plugin based on gRPC.
func NewGRPCPlugin(name string, addr string, opts ...plugin.Option) sd.SD {
var options plugin.Options
for _, opt := range opts {
opt(&options)
}
conn, err := plugin.NewGRPCConn(addr, &options)
if err != nil {
// Connection error is logged by the gRPC dialer; the plugin
// will silently no-op all operations until the connection is
// established (client stays nil).
}
p := &grpcPlugin{
conn: conn,
}
if conn != nil {
p.client = proto.NewSDClient(conn)
}
return p
}
func (p *grpcPlugin) Register(ctx context.Context, service *sd.Service, opts ...sd.Option) error {
if p.client == nil || service == nil {
return nil
}
_, err := p.client.Register(ctx,
&proto.RegisterRequest{
Service: &proto.Service{
Id: service.ID,
Name: service.Name,
Node: service.Node,
Network: service.Network,
Address: service.Address,
},
})
return err
}
func (p *grpcPlugin) Deregister(ctx context.Context, service *sd.Service) error {
if p.client == nil || service == nil {
return nil
}
_, err := p.client.Deregister(ctx, &proto.DeregisterRequest{
Service: &proto.Service{
Id: service.ID,
Name: service.Name,
Node: service.Node,
Network: service.Network,
Address: service.Address,
},
})
return err
}
func (p *grpcPlugin) Renew(ctx context.Context, service *sd.Service) error {
if p.client == nil || service == nil {
return nil
}
_, err := p.client.Renew(ctx, &proto.RenewRequest{
Service: &proto.Service{
Id: service.ID,
Name: service.Name,
Node: service.Node,
Network: service.Network,
Address: service.Address,
},
})
return err
}
func (p *grpcPlugin) Get(ctx context.Context, name string) ([]*sd.Service, error) {
if p.client == nil {
return nil, nil
}
r, err := p.client.Get(ctx, &proto.GetServiceRequest{
Name: name,
})
if err != nil {
return nil, err
}
var services []*sd.Service
for _, v := range r.Services {
if v == nil {
continue
}
services = append(services, &sd.Service{
ID: v.Id,
Name: v.Name,
Node: v.Node,
Network: v.Network,
Address: v.Address,
})
}
return services, nil
}
func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok {
return closer.Close()
}
return nil
}