diff --git a/client/proto/client.micro.go b/client/proto/client.micro.go index d8c9ad88..6fc4886e 100644 --- a/client/proto/client.micro.go +++ b/client/proto/client.micro.go @@ -31,37 +31,37 @@ var _ context.Context var _ client.Option var _ server.Option -// Client API for Micro service +// Client API for Client service -type MicroService interface { +type ClientService interface { // Call allows a single request to be made Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) // Stream is a bidirectional stream - Stream(ctx context.Context, opts ...client.CallOption) (Micro_StreamService, error) + Stream(ctx context.Context, opts ...client.CallOption) (Client_StreamService, error) // Publish publishes a message and returns an empty Message Publish(ctx context.Context, in *Message, opts ...client.CallOption) (*Message, error) } -type microService struct { +type clientService struct { c client.Client name string } -func NewMicroService(name string, c client.Client) MicroService { +func NewClientService(name string, c client.Client) ClientService { if c == nil { c = client.NewClient() } if len(name) == 0 { name = "go.micro.client" } - return µService{ + return &clientService{ c: c, name: name, } } -func (c *microService) Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) { - req := c.c.NewRequest(c.name, "Micro.Call", in) +func (c *clientService) Call(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) { + req := c.c.NewRequest(c.name, "Client.Call", in) out := new(Response) err := c.c.Call(ctx, req, out, opts...) if err != nil { @@ -70,16 +70,16 @@ func (c *microService) Call(ctx context.Context, in *Request, opts ...client.Cal return out, nil } -func (c *microService) Stream(ctx context.Context, opts ...client.CallOption) (Micro_StreamService, error) { - req := c.c.NewRequest(c.name, "Micro.Stream", &Request{}) +func (c *clientService) Stream(ctx context.Context, opts ...client.CallOption) (Client_StreamService, error) { + req := c.c.NewRequest(c.name, "Client.Stream", &Request{}) stream, err := c.c.Stream(ctx, req, opts...) if err != nil { return nil, err } - return µServiceStream{stream}, nil + return &clientServiceStream{stream}, nil } -type Micro_StreamService interface { +type Client_StreamService interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error @@ -87,27 +87,27 @@ type Micro_StreamService interface { Recv() (*Response, error) } -type microServiceStream struct { +type clientServiceStream struct { stream client.Stream } -func (x *microServiceStream) Close() error { +func (x *clientServiceStream) Close() error { return x.stream.Close() } -func (x *microServiceStream) SendMsg(m interface{}) error { +func (x *clientServiceStream) SendMsg(m interface{}) error { return x.stream.Send(m) } -func (x *microServiceStream) RecvMsg(m interface{}) error { +func (x *clientServiceStream) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *microServiceStream) Send(m *Request) error { +func (x *clientServiceStream) Send(m *Request) error { return x.stream.Send(m) } -func (x *microServiceStream) Recv() (*Response, error) { +func (x *clientServiceStream) Recv() (*Response, error) { m := new(Response) err := x.stream.Recv(m) if err != nil { @@ -116,8 +116,8 @@ func (x *microServiceStream) Recv() (*Response, error) { return m, nil } -func (c *microService) Publish(ctx context.Context, in *Message, opts ...client.CallOption) (*Message, error) { - req := c.c.NewRequest(c.name, "Micro.Publish", in) +func (c *clientService) Publish(ctx context.Context, in *Message, opts ...client.CallOption) (*Message, error) { + req := c.c.NewRequest(c.name, "Client.Publish", in) out := new(Message) err := c.c.Call(ctx, req, out, opts...) if err != nil { @@ -126,43 +126,43 @@ func (c *microService) Publish(ctx context.Context, in *Message, opts ...client. return out, nil } -// Server API for Micro service +// Server API for Client service -type MicroHandler interface { +type ClientHandler interface { // Call allows a single request to be made Call(context.Context, *Request, *Response) error // Stream is a bidirectional stream - Stream(context.Context, Micro_StreamStream) error + Stream(context.Context, Client_StreamStream) error // Publish publishes a message and returns an empty Message Publish(context.Context, *Message, *Message) error } -func RegisterMicroHandler(s server.Server, hdlr MicroHandler, opts ...server.HandlerOption) error { - type micro interface { +func RegisterClientHandler(s server.Server, hdlr ClientHandler, opts ...server.HandlerOption) error { + type client interface { Call(ctx context.Context, in *Request, out *Response) error Stream(ctx context.Context, stream server.Stream) error Publish(ctx context.Context, in *Message, out *Message) error } - type Micro struct { - micro + type Client struct { + client } - h := µHandler{hdlr} - return s.Handle(s.NewHandler(&Micro{h}, opts...)) + h := &clientHandler{hdlr} + return s.Handle(s.NewHandler(&Client{h}, opts...)) } -type microHandler struct { - MicroHandler +type clientHandler struct { + ClientHandler } -func (h *microHandler) Call(ctx context.Context, in *Request, out *Response) error { - return h.MicroHandler.Call(ctx, in, out) +func (h *clientHandler) Call(ctx context.Context, in *Request, out *Response) error { + return h.ClientHandler.Call(ctx, in, out) } -func (h *microHandler) Stream(ctx context.Context, stream server.Stream) error { - return h.MicroHandler.Stream(ctx, µStreamStream{stream}) +func (h *clientHandler) Stream(ctx context.Context, stream server.Stream) error { + return h.ClientHandler.Stream(ctx, &clientStreamStream{stream}) } -type Micro_StreamStream interface { +type Client_StreamStream interface { SendMsg(interface{}) error RecvMsg(interface{}) error Close() error @@ -170,27 +170,27 @@ type Micro_StreamStream interface { Recv() (*Request, error) } -type microStreamStream struct { +type clientStreamStream struct { stream server.Stream } -func (x *microStreamStream) Close() error { +func (x *clientStreamStream) Close() error { return x.stream.Close() } -func (x *microStreamStream) SendMsg(m interface{}) error { +func (x *clientStreamStream) SendMsg(m interface{}) error { return x.stream.Send(m) } -func (x *microStreamStream) RecvMsg(m interface{}) error { +func (x *clientStreamStream) RecvMsg(m interface{}) error { return x.stream.Recv(m) } -func (x *microStreamStream) Send(m *Response) error { +func (x *clientStreamStream) Send(m *Response) error { return x.stream.Send(m) } -func (x *microStreamStream) Recv() (*Request, error) { +func (x *clientStreamStream) Recv() (*Request, error) { m := new(Request) if err := x.stream.Recv(m); err != nil { return nil, err @@ -198,6 +198,6 @@ func (x *microStreamStream) Recv() (*Request, error) { return m, nil } -func (h *microHandler) Publish(ctx context.Context, in *Message, out *Message) error { - return h.MicroHandler.Publish(ctx, in, out) +func (h *clientHandler) Publish(ctx context.Context, in *Message, out *Message) error { + return h.ClientHandler.Publish(ctx, in, out) } diff --git a/client/proto/client.pb.go b/client/proto/client.pb.go index 2052f077..c923e337 100644 --- a/client/proto/client.pb.go +++ b/client/proto/client.pb.go @@ -191,23 +191,23 @@ func init() { var fileDescriptor_7d733ae29171347b = []byte{ // 270 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0x3f, 0x4f, 0xc3, 0x30, - 0x10, 0xc5, 0xeb, 0xfe, 0x4b, 0x39, 0x2a, 0x21, 0x9d, 0x18, 0x4c, 0x06, 0x54, 0x32, 0x65, 0xc1, - 0x45, 0x30, 0x23, 0x86, 0xce, 0x95, 0x50, 0x40, 0xac, 0x28, 0x71, 0x4f, 0xc1, 0x52, 0x6a, 0x9b, - 0xd8, 0xad, 0x94, 0xef, 0xc8, 0x87, 0x42, 0x38, 0x29, 0x45, 0xd0, 0x2e, 0x6c, 0xf7, 0xee, 0x67, - 0xbd, 0x3b, 0xbf, 0x83, 0x74, 0xad, 0x64, 0x6d, 0xe6, 0xa5, 0xb9, 0x6e, 0x0b, 0x59, 0x29, 0xd2, - 0x7e, 0x6e, 0x6b, 0xe3, 0x77, 0x42, 0x04, 0x81, 0x67, 0xa5, 0x11, 0xe1, 0x8d, 0x68, 0xdb, 0xc9, - 0x16, 0xa2, 0x8c, 0xde, 0x37, 0xe4, 0x3c, 0x72, 0x88, 0x1c, 0xd5, 0x5b, 0x25, 0x89, 0xb3, 0x19, - 0x4b, 0x4f, 0xb2, 0x9d, 0xc4, 0x18, 0x26, 0xa4, 0x57, 0xd6, 0x28, 0xed, 0x79, 0x3f, 0xa0, 0x6f, - 0x8d, 0x57, 0x30, 0x95, 0x46, 0x7b, 0xd2, 0xfe, 0xd5, 0x37, 0x96, 0xf8, 0x20, 0xf0, 0xd3, 0xae, - 0xf7, 0xdc, 0x58, 0x42, 0x84, 0x61, 0x61, 0x56, 0x0d, 0x1f, 0xce, 0x58, 0x3a, 0xcd, 0x42, 0x9d, - 0x5c, 0xc2, 0x24, 0x23, 0x67, 0x8d, 0x76, 0x7b, 0xce, 0x7e, 0xf0, 0x17, 0x88, 0x96, 0xe4, 0x5c, - 0x5e, 0x12, 0x9e, 0xc3, 0xc8, 0x1b, 0xab, 0x64, 0xb7, 0x55, 0x2b, 0xfe, 0xcc, 0xed, 0x1f, 0x9f, - 0x3b, 0xd8, 0xfb, 0xde, 0x7e, 0x30, 0x18, 0x2d, 0xbf, 0x02, 0xc0, 0x7b, 0x18, 0x2e, 0xf2, 0xaa, - 0x42, 0x2e, 0x7e, 0x65, 0x22, 0xba, 0x40, 0xe2, 0x8b, 0x03, 0xa4, 0x5d, 0x39, 0xe9, 0xe1, 0x02, - 0xc6, 0x4f, 0xbe, 0xa6, 0x7c, 0xfd, 0x4f, 0x83, 0x94, 0xdd, 0x30, 0x7c, 0x80, 0xe8, 0x71, 0x53, - 0x54, 0xca, 0xbd, 0x1d, 0x70, 0xe9, 0xfe, 0x1f, 0x1f, 0x25, 0x49, 0xaf, 0x18, 0x87, 0xb3, 0xde, - 0x7d, 0x06, 0x00, 0x00, 0xff, 0xff, 0xd3, 0x63, 0x94, 0x1a, 0x02, 0x02, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0x41, 0x4b, 0xc3, 0x40, + 0x10, 0x85, 0xbb, 0x6d, 0x4c, 0xea, 0x58, 0x10, 0x06, 0x0f, 0x6b, 0x0e, 0x52, 0x73, 0xca, 0xc5, + 0x54, 0xf4, 0x2c, 0x1e, 0x72, 0x16, 0x24, 0x8a, 0x57, 0x49, 0xb6, 0x43, 0x5c, 0x48, 0x77, 0xd7, + 0xec, 0xb6, 0x90, 0x1f, 0xe9, 0x7f, 0x12, 0x36, 0xa9, 0x15, 0x6d, 0x2f, 0xbd, 0xcd, 0x9b, 0x6f, + 0x79, 0x33, 0xfb, 0x06, 0xd2, 0x95, 0x14, 0xad, 0x5e, 0xd4, 0xfa, 0xa6, 0x2f, 0x44, 0x23, 0x49, + 0xb9, 0x85, 0x69, 0xb5, 0xdb, 0x8a, 0xcc, 0x0b, 0x3c, 0xaf, 0x75, 0xe6, 0xdf, 0x64, 0x7d, 0x3b, + 0xd9, 0x40, 0x54, 0xd0, 0xe7, 0x9a, 0xac, 0x43, 0x0e, 0x91, 0xa5, 0x76, 0x23, 0x05, 0x71, 0x36, + 0x67, 0xe9, 0x69, 0xb1, 0x95, 0x18, 0xc3, 0x94, 0xd4, 0xd2, 0x68, 0xa9, 0x1c, 0x1f, 0x7b, 0xf4, + 0xa3, 0xf1, 0x1a, 0x66, 0x42, 0x2b, 0x47, 0xca, 0xbd, 0xbb, 0xce, 0x10, 0x9f, 0x78, 0x7e, 0x36, + 0xf4, 0x5e, 0x3b, 0x43, 0x88, 0x10, 0x54, 0x7a, 0xd9, 0xf1, 0x60, 0xce, 0xd2, 0x59, 0xe1, 0xeb, + 0xe4, 0x0a, 0xa6, 0x05, 0x59, 0xa3, 0x95, 0xdd, 0x71, 0xf6, 0x8b, 0xbf, 0x41, 0xf4, 0x44, 0xd6, + 0x96, 0x35, 0xe1, 0x05, 0x9c, 0x38, 0x6d, 0xa4, 0x18, 0xb6, 0xea, 0xc5, 0xbf, 0xb9, 0xe3, 0xc3, + 0x73, 0x27, 0x3b, 0xdf, 0xbb, 0x2f, 0x06, 0x61, 0xee, 0xbf, 0x8e, 0x0f, 0x10, 0xe4, 0x65, 0xd3, + 0x20, 0xcf, 0xfe, 0x84, 0x92, 0x0d, 0x89, 0xc4, 0x97, 0x7b, 0x48, 0xbf, 0x73, 0x32, 0xc2, 0x1c, + 0xc2, 0x17, 0xd7, 0x52, 0xb9, 0x3a, 0xd2, 0x20, 0x65, 0xb7, 0x0c, 0x1f, 0x21, 0x7a, 0x5e, 0x57, + 0x8d, 0xb4, 0x1f, 0x7b, 0x5c, 0x86, 0x00, 0xe2, 0x83, 0x24, 0x19, 0x55, 0xa1, 0xbf, 0xeb, 0xfd, + 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x76, 0x1f, 0x51, 0x03, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -218,59 +218,59 @@ var _ grpc.ClientConn // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion4 -// MicroClient is the client API for Micro service. +// ClientClient is the client API for Client service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type MicroClient interface { +type ClientClient interface { // Call allows a single request to be made Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) // Stream is a bidirectional stream - Stream(ctx context.Context, opts ...grpc.CallOption) (Micro_StreamClient, error) + Stream(ctx context.Context, opts ...grpc.CallOption) (Client_StreamClient, error) // Publish publishes a message and returns an empty Message Publish(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) } -type microClient struct { +type clientClient struct { cc *grpc.ClientConn } -func NewMicroClient(cc *grpc.ClientConn) MicroClient { - return µClient{cc} +func NewClientClient(cc *grpc.ClientConn) ClientClient { + return &clientClient{cc} } -func (c *microClient) Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { +func (c *clientClient) Call(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) { out := new(Response) - err := c.cc.Invoke(ctx, "/go.micro.client.Micro/Call", in, out, opts...) + err := c.cc.Invoke(ctx, "/go.micro.client.Client/Call", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *microClient) Stream(ctx context.Context, opts ...grpc.CallOption) (Micro_StreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_Micro_serviceDesc.Streams[0], "/go.micro.client.Micro/Stream", opts...) +func (c *clientClient) Stream(ctx context.Context, opts ...grpc.CallOption) (Client_StreamClient, error) { + stream, err := c.cc.NewStream(ctx, &_Client_serviceDesc.Streams[0], "/go.micro.client.Client/Stream", opts...) if err != nil { return nil, err } - x := µStreamClient{stream} + x := &clientStreamClient{stream} return x, nil } -type Micro_StreamClient interface { +type Client_StreamClient interface { Send(*Request) error Recv() (*Response, error) grpc.ClientStream } -type microStreamClient struct { +type clientStreamClient struct { grpc.ClientStream } -func (x *microStreamClient) Send(m *Request) error { +func (x *clientStreamClient) Send(m *Request) error { return x.ClientStream.SendMsg(m) } -func (x *microStreamClient) Recv() (*Response, error) { +func (x *clientStreamClient) Recv() (*Response, error) { m := new(Response) if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err @@ -278,66 +278,66 @@ func (x *microStreamClient) Recv() (*Response, error) { return m, nil } -func (c *microClient) Publish(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) { +func (c *clientClient) Publish(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) { out := new(Message) - err := c.cc.Invoke(ctx, "/go.micro.client.Micro/Publish", in, out, opts...) + err := c.cc.Invoke(ctx, "/go.micro.client.Client/Publish", in, out, opts...) if err != nil { return nil, err } return out, nil } -// MicroServer is the server API for Micro service. -type MicroServer interface { +// ClientServer is the server API for Client service. +type ClientServer interface { // Call allows a single request to be made Call(context.Context, *Request) (*Response, error) // Stream is a bidirectional stream - Stream(Micro_StreamServer) error + Stream(Client_StreamServer) error // Publish publishes a message and returns an empty Message Publish(context.Context, *Message) (*Message, error) } -func RegisterMicroServer(s *grpc.Server, srv MicroServer) { - s.RegisterService(&_Micro_serviceDesc, srv) +func RegisterClientServer(s *grpc.Server, srv ClientServer) { + s.RegisterService(&_Client_serviceDesc, srv) } -func _Micro_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _Client_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(Request) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MicroServer).Call(ctx, in) + return srv.(ClientServer).Call(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/go.micro.client.Micro/Call", + FullMethod: "/go.micro.client.Client/Call", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MicroServer).Call(ctx, req.(*Request)) + return srv.(ClientServer).Call(ctx, req.(*Request)) } return interceptor(ctx, in, info, handler) } -func _Micro_Stream_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(MicroServer).Stream(µStreamServer{stream}) +func _Client_Stream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ClientServer).Stream(&clientStreamServer{stream}) } -type Micro_StreamServer interface { +type Client_StreamServer interface { Send(*Response) error Recv() (*Request, error) grpc.ServerStream } -type microStreamServer struct { +type clientStreamServer struct { grpc.ServerStream } -func (x *microStreamServer) Send(m *Response) error { +func (x *clientStreamServer) Send(m *Response) error { return x.ServerStream.SendMsg(m) } -func (x *microStreamServer) Recv() (*Request, error) { +func (x *clientStreamServer) Recv() (*Request, error) { m := new(Request) if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err @@ -345,41 +345,41 @@ func (x *microStreamServer) Recv() (*Request, error) { return m, nil } -func _Micro_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _Client_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(Message) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MicroServer).Publish(ctx, in) + return srv.(ClientServer).Publish(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/go.micro.client.Micro/Publish", + FullMethod: "/go.micro.client.Client/Publish", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MicroServer).Publish(ctx, req.(*Message)) + return srv.(ClientServer).Publish(ctx, req.(*Message)) } return interceptor(ctx, in, info, handler) } -var _Micro_serviceDesc = grpc.ServiceDesc{ - ServiceName: "go.micro.client.Micro", - HandlerType: (*MicroServer)(nil), +var _Client_serviceDesc = grpc.ServiceDesc{ + ServiceName: "go.micro.client.Client", + HandlerType: (*ClientServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "Call", - Handler: _Micro_Call_Handler, + Handler: _Client_Call_Handler, }, { MethodName: "Publish", - Handler: _Micro_Publish_Handler, + Handler: _Client_Publish_Handler, }, }, Streams: []grpc.StreamDesc{ { StreamName: "Stream", - Handler: _Micro_Stream_Handler, + Handler: _Client_Stream_Handler, ServerStreams: true, ClientStreams: true, }, diff --git a/client/proto/client.proto b/client/proto/client.proto index b855fa22..b5703cf2 100644 --- a/client/proto/client.proto +++ b/client/proto/client.proto @@ -2,8 +2,8 @@ syntax = "proto3"; package go.micro.client; -// Micro is the micro client interface -service Micro { +// Client is the micro client interface +service Client { // Call allows a single request to be made rpc Call(Request) returns (Response) {}; // Stream is a bidirectional stream diff --git a/proxy/grpc/grpc.go b/proxy/grpc/grpc.go index afb2453c..89947054 100644 --- a/proxy/grpc/grpc.go +++ b/proxy/grpc/grpc.go @@ -10,6 +10,7 @@ import ( "github.com/micro/go-micro/client/grpc" "github.com/micro/go-micro/codec" "github.com/micro/go-micro/config/options" + "github.com/micro/go-micro/errors" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/server" ) @@ -61,6 +62,10 @@ func readLoop(r server.Request, s client.Stream) error { } } +func (p *Proxy) SendRequest(ctx context.Context, req client.Request, rsp client.Response) error { + return errors.InternalServerError("go.micro.proxy.grpc", "SendRequest is unsupported") +} + // ServeRequest honours the server.Proxy interface func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error { // set default client diff --git a/proxy/http/http.go b/proxy/http/http.go index 61a6fc06..37ef1f87 100644 --- a/proxy/http/http.go +++ b/proxy/http/http.go @@ -10,6 +10,7 @@ import ( "net/url" "path" + "github.com/micro/go-micro/client" "github.com/micro/go-micro/config/options" "github.com/micro/go-micro/errors" "github.com/micro/go-micro/proxy" @@ -44,6 +45,10 @@ func getEndpoint(hdr map[string]string) string { return "" } +func (p *Proxy) SendRequest(ctx context.Context, req client.Request, rsp client.Response) error { + return errors.InternalServerError("go.micro.proxy.http", "SendRequest is unsupported") +} + // ServeRequest honours the server.Router interface func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error { if p.Endpoint == "" { diff --git a/proxy/mucp/mucp.go b/proxy/mucp/mucp.go index 095c10d8..ec95f407 100644 --- a/proxy/mucp/mucp.go +++ b/proxy/mucp/mucp.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "io" + "sort" "strings" "sync" @@ -12,6 +13,7 @@ import ( "github.com/micro/go-micro/codec" "github.com/micro/go-micro/codec/bytes" "github.com/micro/go-micro/config/options" + "github.com/micro/go-micro/errors" "github.com/micro/go-micro/proxy" "github.com/micro/go-micro/router" "github.com/micro/go-micro/server" @@ -26,9 +28,12 @@ type Proxy struct { // Endpoint specifies the fixed service endpoint to call. Endpoint string - // The client to use for outbound requests + // The client to use for outbound requests in the local network Client client.Client + // Links are used for outbound requests not in the local network + Links map[string]client.Client + // The router for routes Router router.Router @@ -76,7 +81,7 @@ func readLoop(r server.Request, s client.Stream) error { } // toNodes returns a list of node addresses from given routes -func toNodes(routes map[uint64]router.Route) []string { +func toNodes(routes []router.Route) []string { var nodes []string for _, node := range routes { address := node.Address @@ -88,15 +93,37 @@ func toNodes(routes map[uint64]router.Route) []string { return nodes } -func (p *Proxy) getRoute(service string) ([]string, error) { +func (p *Proxy) getLink(r router.Route) (client.Client, error) { + if r.Link == "local" || len(p.Links) == 0 { + return p.Client, nil + } + l, ok := p.Links[r.Link] + if !ok { + return nil, errors.InternalServerError("go.micro.proxy", "link not found") + } + return l, nil +} + +func (p *Proxy) getRoute(service string) ([]router.Route, error) { + toSlice := func(r map[uint64]router.Route) []router.Route { + var routes []router.Route + for _, v := range r { + routes = append(routes, v) + } + + // sort the routes in order of metric + sort.Slice(routes, func(i, j int) bool { return routes[i].Metric < routes[j].Metric }) + + return routes + } + // lookup the route cache first p.Lock() routes, ok := p.Routes[service] if ok { p.Unlock() - return toNodes(routes), nil + return toSlice(routes), nil } - p.Routes[service] = make(map[uint64]router.Route) p.Unlock() // lookup the routes in the router @@ -113,12 +140,16 @@ func (p *Proxy) getRoute(service string) ([]string, error) { // update the proxy cache p.Lock() for _, route := range results { + // create if does not exist + if _, ok := p.Routes[service]; !ok { + p.Routes[service] = make(map[uint64]router.Route) + } p.Routes[service][route.Hash()] = route } routes = p.Routes[service] p.Unlock() - return toNodes(routes), nil + return toSlice(routes), nil } // manageRouteCache applies action on a given route to Proxy route cache @@ -171,12 +202,27 @@ func (p *Proxy) watchRoutes() { } } +func (p *Proxy) SendRequest(ctx context.Context, req client.Request, rsp client.Response) error { + return errors.InternalServerError("go.micro.proxy", "SendRequest is unsupported") +} + // ServeRequest honours the server.Router interface func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server.Response) error { - // service name - service := req.Service() - endpoint := req.Endpoint() + // determine if its local routing + var local bool + // address to call var addresses []string + // routes + var routes []router.Route + // service name to call + service := req.Service() + // endpoint to call + endpoint := req.Endpoint() + + // are we network routing or local routing + if len(p.Links) == 0 { + local = true + } // call a specific backend endpoint either by name or address if len(p.Endpoint) > 0 { @@ -190,7 +236,7 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server return err } // set the address - addresses = addr + routes = addr // set the name service = p.Endpoint } @@ -201,16 +247,66 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server if err != nil { return err } - addresses = addr + routes = addr } - var opts []client.CallOption - - // set address if available + // if the address is already set just serve it + // TODO: figure it out if we should know to pick a link if len(addresses) > 0 { - opts = append(opts, client.WithAddress(addresses...)) + // serve the normal way + return p.serveRequest(ctx, p.Client, service, endpoint, req, rsp, client.WithAddress(addresses...)) } + // there's no links e.g we're local routing then just serve it with addresses + if local { + var opts []client.CallOption + + // set address if available via routes or specific endpoint + if len(routes) > 0 { + addresses := toNodes(routes) + opts = append(opts, client.WithAddress(addresses...)) + } + + // serve the normal way + return p.serveRequest(ctx, p.Client, service, endpoint, req, rsp, opts...) + } + + var gerr error + + // we're routing globally with multiple links + // so we need to pick a link per route + for _, route := range routes { + // pick the link or error out + link, err := p.getLink(route) + if err != nil { + // ok let's try again + gerr = err + continue + } + + // set the address to call + addresses := toNodes([]router.Route{route}) + + // do the request with the link + gerr = p.serveRequest(ctx, link, service, endpoint, req, rsp, client.WithAddress(addresses...)) + // return on no error since we succeeded + if gerr == nil { + return nil + } + + // return where the context deadline was exceeded + if gerr == context.Canceled || gerr == context.DeadlineExceeded { + return err + } + + // otherwise attempt to do it all over again + } + + // if we got here something went really badly wrong + return gerr +} + +func (p *Proxy) serveRequest(ctx context.Context, link client.Client, service, endpoint string, req server.Request, rsp server.Response, opts ...client.CallOption) error { // read initial request body, err := req.Read() if err != nil { @@ -218,14 +314,14 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server } // create new request with raw bytes body - creq := p.Client.NewRequest(service, endpoint, &bytes.Frame{body}, client.WithContentType(req.ContentType())) + creq := link.NewRequest(service, endpoint, &bytes.Frame{body}, client.WithContentType(req.ContentType())) // not a stream so make a client.Call request if !req.Stream() { crsp := new(bytes.Frame) // make a call to the backend - if err := p.Client.Call(ctx, creq, crsp, opts...); err != nil { + if err := link.Call(ctx, creq, crsp, opts...); err != nil { return err } @@ -238,7 +334,7 @@ func (p *Proxy) ServeRequest(ctx context.Context, req server.Request, rsp server } // create new stream - stream, err := p.Client.Stream(ctx, creq, opts...) + stream, err := link.Stream(ctx, creq, opts...) if err != nil { return err } @@ -300,6 +396,7 @@ func NewSingleHostProxy(endpoint string) *Proxy { // NewProxy returns a new proxy which will route based on mucp headers func NewProxy(opts ...options.Option) proxy.Proxy { p := new(Proxy) + p.Links = map[string]client.Client{} p.Options = options.NewOptions(opts...) p.Options.Init(options.WithString("mucp")) @@ -320,6 +417,12 @@ func NewProxy(opts ...options.Option) proxy.Proxy { p.Client = client.DefaultClient } + // get client + links, ok := p.Options.Values().Get("proxy.links") + if ok { + p.Links = links.(map[string]client.Client) + } + // get router r, ok := p.Options.Values().Get("proxy.router") if ok { diff --git a/proxy/proxy.go b/proxy/proxy.go index cec226ba..e91eaf0f 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -13,6 +13,8 @@ import ( // Proxy can be used as a proxy server for go-micro services type Proxy interface { options.Options + // SendRequest honours the client.Router interface + SendRequest(context.Context, client.Request, client.Response) error // ServeRequest honours the server.Router interface ServeRequest(context.Context, server.Request, server.Response) error } @@ -35,3 +37,20 @@ func WithClient(c client.Client) options.Option { func WithRouter(r router.Router) options.Option { return options.WithValue("proxy.router", r) } + +// WithLink sets a link for outbound requests +func WithLink(name string, c client.Client) options.Option { + return func(o *options.Values) error { + var links map[string]client.Client + v, ok := o.Get("proxy.links") + if ok { + links = v.(map[string]client.Client) + } else { + links = map[string]client.Client{} + } + links[name] = c + // save the links + o.Set("proxy.links", links) + return nil + } +}