Compare commits
139 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1222d076f2 | ||
|
76ade7efd9 | ||
c706ebe3fb | |||
9e6db79860 | |||
756b346672 | |||
|
4db2f5e79d | ||
3d7d5ce6b4 | |||
|
8282e781e4 | ||
e4acc63d5f | |||
|
45ee5e9ad1 | ||
|
b60fde0e64 | ||
|
011a783a9e | ||
|
6723d17b22 | ||
|
47c7181d41 | ||
b38da6ced0 | |||
|
1a53307a78 | ||
|
e204f3e2e8 | ||
|
329bd09f93 | ||
|
4648fd0d09 | ||
|
c905df3be6 | ||
|
62f9a054a4 | ||
|
00e7804f96 | ||
|
42b6bf5bbf | ||
|
844c456839 | ||
|
7182ca1fd0 | ||
02839cfba5 | |||
|
776a7d6cd6 | ||
beaa434610 | |||
|
6efc5556e5 | ||
|
8d0826a031 | ||
|
378d03eb66 | ||
|
56af826230 | ||
|
511ebd8ec2 | ||
|
1057ef6acb | ||
|
35e2a68a98 | ||
|
0e56382107 | ||
|
dff98355be | ||
8100d26430 | |||
|
397a8638f4 | ||
|
eb4d2ae6aa | ||
|
914340585c | ||
|
84b4eb5404 | ||
|
fd664f4392 | ||
|
86272a3064 | ||
|
c1978265ab | ||
|
e0e77f3983 | ||
9826ddbd64 | |||
|
87617be227 | ||
d559587807 | |||
|
9501512219 | ||
|
d2f153d795 | ||
|
e49be1da42 | ||
|
4c6f68d537 | ||
cbb958def5 | |||
|
40ff6ddfcf | ||
|
5ad7c36bd4 | ||
|
99c3fe2bb8 | ||
|
1bd340701b | ||
|
c91bf7e9e7 | ||
41f8a8cb00 | |||
|
cd04111e3d | ||
|
00cd2448a4 | ||
|
8a41d369f2 | ||
|
638c219736 | ||
|
b3c631dd38 | ||
ab73127063 | |||
|
03031a694d | ||
|
5712aafba9 | ||
ac333d9d47 | |||
|
247707f583 | ||
|
d91c14eb30 | ||
|
ca8684a886 | ||
|
0449138f61 | ||
609f4826b3 | |||
60993e6275 | |||
|
e803fb0855 | ||
3543b275e0 | |||
fbde872e7f | |||
|
078dd4eb9b | ||
62a644ddd8 | |||
|
d8cfa7a295 | ||
|
47f1203e97 | ||
|
1b4e881d74 | ||
|
20ce61da5a | ||
|
eef4825be4 | ||
|
be9c6141f5 | ||
|
1ca4619506 | ||
|
f55493993c | ||
7b385bf163 | |||
|
4125ae8d53 | ||
|
48b2a5c37c | ||
|
ed83c27f0e | ||
241614ff68 | |||
|
1a4f608ed1 | ||
43b0dbb123 | |||
|
b344171c80 | ||
|
e3ce45495a | ||
f01664a551 | |||
8ecbdc1cd6 | |||
55c19afb0b | |||
077063c212 | |||
|
9a7a65f05e | ||
8ee5607254 | |||
11be2c68b9 | |||
a864f812f1 | |||
|
ae60bea8d8 | ||
|
a851b9db7a | ||
d807dac2a7 | |||
ce2ba71002 | |||
|
67c26c71b6 | ||
|
9386f36a13 | ||
|
6d803d9e45 | ||
|
6a9001bdb1 | ||
|
3f0c28a815 | ||
|
49ffc60afb | ||
|
beb5e80e87 | ||
|
eebd69c995 | ||
|
bc71989e2c | ||
89ba602e17 | |||
|
f6102bde70 | ||
|
7cad77bfc0 | ||
|
1f2e067f71 | ||
b555269b1b | |||
|
9200c70202 | ||
|
d8377e09c9 | ||
0754229878 | |||
6b8930a960 | |||
d0a978bd50 | |||
|
afe6861e2f | ||
|
962567ef42 | ||
|
e21ed3a183 | ||
64a5ce9607 | |||
|
d651b16acd | ||
|
1034837f69 | ||
|
80f2bfd5d0 | ||
|
6aaaf54275 | ||
|
603d37b135 | ||
|
53c3bff819 | ||
|
dcf859098b |
9
.github/generate.sh
vendored
Executable file
9
.github/generate.sh
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
find . -type f -name '*.pb.*.go' -o -name '*.pb.go' -a ! -name 'message.pb.go' -delete
|
||||
PROTOS=$(find . -type f -name '*.proto')
|
||||
|
||||
for PROTO in $PROTOS; do
|
||||
echo $PROTO
|
||||
protoc -I./ -I$(dirname $PROTO) --go_out=plugins=grpc,paths=source_relative:. --micro_out=paths=source_relative:. $PROTO
|
||||
done
|
@@ -5,7 +5,7 @@ RUN mkdir /user && \
|
||||
echo 'nobody:x:65534:' > /user/group
|
||||
|
||||
ENV GO111MODULE=on
|
||||
RUN apk --no-cache add make git gcc libtool musl-dev ca-certificates && \
|
||||
RUN apk --no-cache add make git gcc libtool musl-dev ca-certificates dumb-init && \
|
||||
rm -rf /var/cache/apk/* /tmp/*
|
||||
|
||||
WORKDIR /
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type discordConn struct {
|
||||
@@ -74,7 +74,9 @@ func (dc *discordConn) Send(e *input.Event) error {
|
||||
fields := strings.Split(e.To, ":")
|
||||
_, err := dc.master.session.ChannelMessageSend(fields[0], string(e.Data))
|
||||
if err != nil {
|
||||
log.Error("[bot][loop][send]", err)
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error("[bot][loop][send]", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/forestgiant/sliceutil"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
tgbotapi "gopkg.in/telegram-bot-api.v4"
|
||||
)
|
||||
|
||||
@@ -104,7 +104,9 @@ func (tc *telegramConn) Send(event *input.Event) error {
|
||||
|
||||
if err != nil {
|
||||
// probably it could be because of nested HTML tags -- telegram doesn't allow nested tags
|
||||
log.Error("[telegram][Send] error:", err)
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error("[telegram][Send] error:", err)
|
||||
}
|
||||
msgConfig.Text = "This bot couldn't send the response (Internal error)"
|
||||
tc.input.api.Send(msgConfig)
|
||||
}
|
||||
|
@@ -1,11 +1,15 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/v2/agent/proto/bot.proto
|
||||
// source: agent/proto/bot.proto
|
||||
|
||||
package go_micro_bot
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
@@ -30,7 +34,7 @@ func (m *HelpRequest) Reset() { *m = HelpRequest{} }
|
||||
func (m *HelpRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*HelpRequest) ProtoMessage() {}
|
||||
func (*HelpRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_018e8d5b14a89d12, []int{0}
|
||||
return fileDescriptor_79b974b8c77805fa, []int{0}
|
||||
}
|
||||
|
||||
func (m *HelpRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -63,7 +67,7 @@ func (m *HelpResponse) Reset() { *m = HelpResponse{} }
|
||||
func (m *HelpResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*HelpResponse) ProtoMessage() {}
|
||||
func (*HelpResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_018e8d5b14a89d12, []int{1}
|
||||
return fileDescriptor_79b974b8c77805fa, []int{1}
|
||||
}
|
||||
|
||||
func (m *HelpResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -109,7 +113,7 @@ func (m *ExecRequest) Reset() { *m = ExecRequest{} }
|
||||
func (m *ExecRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExecRequest) ProtoMessage() {}
|
||||
func (*ExecRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_018e8d5b14a89d12, []int{2}
|
||||
return fileDescriptor_79b974b8c77805fa, []int{2}
|
||||
}
|
||||
|
||||
func (m *ExecRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -149,7 +153,7 @@ func (m *ExecResponse) Reset() { *m = ExecResponse{} }
|
||||
func (m *ExecResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExecResponse) ProtoMessage() {}
|
||||
func (*ExecResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_018e8d5b14a89d12, []int{3}
|
||||
return fileDescriptor_79b974b8c77805fa, []int{3}
|
||||
}
|
||||
|
||||
func (m *ExecResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -191,26 +195,139 @@ func init() {
|
||||
proto.RegisterType((*ExecResponse)(nil), "go.micro.bot.ExecResponse")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/go-micro/v2/agent/proto/bot.proto", fileDescriptor_018e8d5b14a89d12)
|
||||
func init() { proto.RegisterFile("agent/proto/bot.proto", fileDescriptor_79b974b8c77805fa) }
|
||||
|
||||
var fileDescriptor_79b974b8c77805fa = []byte{
|
||||
// 234 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x3f, 0x4f, 0xc3, 0x30,
|
||||
0x10, 0xc5, 0x1b, 0x28, 0x45, 0xbd, 0x84, 0xc5, 0x02, 0x14, 0x3a, 0x05, 0x4f, 0x9d, 0x5c, 0x09,
|
||||
0x56, 0x24, 0x06, 0x04, 0x62, 0xce, 0x37, 0x48, 0xd2, 0x53, 0x14, 0xa9, 0xf1, 0x99, 0xb3, 0x23,
|
||||
0xf1, 0x1d, 0xf8, 0xd2, 0xc8, 0x7f, 0x06, 0xab, 0xea, 0x76, 0xcf, 0x67, 0xbd, 0xf7, 0x7b, 0x07,
|
||||
0x0f, 0xdd, 0x88, 0xda, 0x1d, 0x0c, 0x93, 0xa3, 0x43, 0x4f, 0x4e, 0x85, 0x49, 0x54, 0x23, 0xa9,
|
||||
0x79, 0x1a, 0x98, 0x54, 0x4f, 0x4e, 0xde, 0x41, 0xf9, 0x8d, 0x27, 0xd3, 0xe2, 0xcf, 0x82, 0xd6,
|
||||
0xc9, 0x2f, 0xa8, 0xa2, 0xb4, 0x86, 0xb4, 0x45, 0x71, 0x0f, 0x37, 0x8b, 0xed, 0x46, 0xac, 0x8b,
|
||||
0xa6, 0xd8, 0x6f, 0xdb, 0x28, 0x44, 0x03, 0xe5, 0x11, 0xed, 0xc0, 0x93, 0x71, 0x13, 0xe9, 0xfa,
|
||||
0x2a, 0xec, 0xf2, 0x27, 0xf9, 0x0c, 0xe5, 0xe7, 0x2f, 0x0e, 0xc9, 0x56, 0x08, 0x58, 0x77, 0x3c,
|
||||
0xda, 0xba, 0x68, 0xae, 0xf7, 0xdb, 0x36, 0xcc, 0xf2, 0x0d, 0xaa, 0xf8, 0x25, 0x45, 0x3d, 0xc2,
|
||||
0x86, 0xd1, 0x2e, 0x27, 0x17, 0xb2, 0xaa, 0x36, 0x29, 0x8f, 0x80, 0xcc, 0xc4, 0x29, 0x26, 0x8a,
|
||||
0x97, 0xbf, 0x02, 0x6e, 0x3f, 0x68, 0x9e, 0x3b, 0x7d, 0x14, 0xef, 0xb0, 0xf6, 0xd0, 0xe2, 0x49,
|
||||
0xe5, 0xd5, 0x54, 0xd6, 0x6b, 0xb7, 0xbb, 0xb4, 0x8a, 0xc1, 0x72, 0xe5, 0x0d, 0x3c, 0xca, 0xb9,
|
||||
0x41, 0xd6, 0xe0, 0xdc, 0x20, 0x27, 0x97, 0xab, 0x7e, 0x13, 0x4e, 0xfb, 0xfa, 0x1f, 0x00, 0x00,
|
||||
0xff, 0xff, 0xe8, 0x08, 0x5e, 0xad, 0x73, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
var fileDescriptor_018e8d5b14a89d12 = []byte{
|
||||
// 246 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x50, 0x4d, 0x4b, 0xc4, 0x30,
|
||||
0x10, 0xdd, 0xea, 0xba, 0xb2, 0xd3, 0x7a, 0x09, 0x22, 0x75, 0x4f, 0x35, 0xa7, 0xbd, 0x98, 0x80,
|
||||
0x5e, 0x05, 0x0f, 0xa2, 0x78, 0xee, 0x3f, 0x68, 0xbb, 0x43, 0x2c, 0x6c, 0x3b, 0x35, 0x99, 0x82,
|
||||
0xff, 0xc1, 0x3f, 0x2d, 0x4d, 0x72, 0x08, 0xc5, 0xdb, 0x7b, 0x79, 0xe1, 0x7d, 0x0c, 0x68, 0xd3,
|
||||
0xf3, 0xd7, 0xdc, 0xaa, 0x8e, 0x06, 0x3d, 0xf4, 0x9d, 0x25, 0x6d, 0xe8, 0x31, 0x80, 0xc6, 0xe0,
|
||||
0xc8, 0x7a, 0xb2, 0xc4, 0xa4, 0x5b, 0x62, 0xe5, 0x91, 0x28, 0x0c, 0x29, 0xaf, 0xab, 0x96, 0x58,
|
||||
0xde, 0x40, 0xfe, 0x89, 0xe7, 0xa9, 0xc6, 0xef, 0x19, 0x1d, 0xcb, 0x0f, 0x28, 0x02, 0x75, 0x13,
|
||||
0x8d, 0x0e, 0xc5, 0x2d, 0x5c, 0xcd, 0xae, 0x31, 0x58, 0x66, 0x55, 0x76, 0xdc, 0xd7, 0x81, 0x88,
|
||||
0x0a, 0xf2, 0x13, 0xba, 0xce, 0xf6, 0x13, 0xf7, 0x34, 0x96, 0x17, 0x5e, 0x4b, 0x9f, 0xe4, 0x03,
|
||||
0xe4, 0xef, 0x3f, 0xd8, 0x45, 0x5b, 0x21, 0x60, 0xdb, 0x58, 0xe3, 0xca, 0xac, 0xba, 0x3c, 0xee,
|
||||
0x6b, 0x8f, 0xe5, 0x0b, 0x14, 0xe1, 0x4b, 0x8c, 0xba, 0x83, 0x9d, 0x45, 0x37, 0x9f, 0xd9, 0x67,
|
||||
0x15, 0x75, 0x64, 0x4b, 0x05, 0xb4, 0x96, 0x6c, 0x8c, 0x09, 0xe4, 0xe9, 0x37, 0x83, 0xeb, 0x37,
|
||||
0x1a, 0x86, 0x66, 0x3c, 0x89, 0x57, 0xd8, 0x2e, 0xa5, 0xc5, 0xbd, 0x4a, 0xa7, 0xa9, 0x64, 0xd7,
|
||||
0xe1, 0xf0, 0x9f, 0x14, 0x82, 0xe5, 0x66, 0x31, 0x58, 0xaa, 0xac, 0x0d, 0x92, 0x05, 0x6b, 0x83,
|
||||
0xb4, 0xb9, 0xdc, 0xb4, 0x3b, 0x7f, 0xda, 0xe7, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0xbd,
|
||||
0x39, 0x29, 0x8d, 0x01, 0x00, 0x00,
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// CommandClient is the client API for Command service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type CommandClient interface {
|
||||
Help(ctx context.Context, in *HelpRequest, opts ...grpc.CallOption) (*HelpResponse, error)
|
||||
Exec(ctx context.Context, in *ExecRequest, opts ...grpc.CallOption) (*ExecResponse, error)
|
||||
}
|
||||
|
||||
type commandClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewCommandClient(cc *grpc.ClientConn) CommandClient {
|
||||
return &commandClient{cc}
|
||||
}
|
||||
|
||||
func (c *commandClient) Help(ctx context.Context, in *HelpRequest, opts ...grpc.CallOption) (*HelpResponse, error) {
|
||||
out := new(HelpResponse)
|
||||
err := c.cc.Invoke(ctx, "/go.micro.bot.Command/Help", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *commandClient) Exec(ctx context.Context, in *ExecRequest, opts ...grpc.CallOption) (*ExecResponse, error) {
|
||||
out := new(ExecResponse)
|
||||
err := c.cc.Invoke(ctx, "/go.micro.bot.Command/Exec", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// CommandServer is the server API for Command service.
|
||||
type CommandServer interface {
|
||||
Help(context.Context, *HelpRequest) (*HelpResponse, error)
|
||||
Exec(context.Context, *ExecRequest) (*ExecResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedCommandServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedCommandServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedCommandServer) Help(ctx context.Context, req *HelpRequest) (*HelpResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Help not implemented")
|
||||
}
|
||||
func (*UnimplementedCommandServer) Exec(ctx context.Context, req *ExecRequest) (*ExecResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Exec not implemented")
|
||||
}
|
||||
|
||||
func RegisterCommandServer(s *grpc.Server, srv CommandServer) {
|
||||
s.RegisterService(&_Command_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Command_Help_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(HelpRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CommandServer).Help(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/go.micro.bot.Command/Help",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CommandServer).Help(ctx, req.(*HelpRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Command_Exec_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ExecRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CommandServer).Exec(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/go.micro.bot.Command/Exec",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CommandServer).Exec(ctx, req.(*ExecRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Command_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "go.micro.bot.Command",
|
||||
HandlerType: (*CommandServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Help",
|
||||
Handler: _Command_Help_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Exec",
|
||||
Handler: _Command_Exec_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "agent/proto/bot.proto",
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/v2/agent/proto/bot.proto
|
||||
// source: agent/proto/bot.proto
|
||||
|
||||
package go_micro_bot
|
||||
|
||||
@@ -44,12 +44,6 @@ type commandService struct {
|
||||
}
|
||||
|
||||
func NewCommandService(name string, c client.Client) CommandService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "go.micro.bot"
|
||||
}
|
||||
return &commandService{
|
||||
c: c,
|
||||
name: name,
|
||||
|
16
api/api.go
16
api/api.go
@@ -9,6 +9,20 @@ import (
|
||||
"github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
type Api interface {
|
||||
// Register a http handler
|
||||
Register(*Endpoint) error
|
||||
// Register a route
|
||||
Deregister(*Endpoint) error
|
||||
// Init initialises the command line.
|
||||
// It also parses further options.
|
||||
//Init(...Option) error
|
||||
// Options
|
||||
//Options() Options
|
||||
// String
|
||||
String() string
|
||||
}
|
||||
|
||||
// Endpoint is a mapping between an RPC method and HTTP endpoint
|
||||
type Endpoint struct {
|
||||
// RPC Method e.g. Greeter.Hello
|
||||
@@ -23,6 +37,8 @@ type Endpoint struct {
|
||||
Method []string
|
||||
// HTTP Path e.g /greeter. Expect POSIX regex
|
||||
Path []string
|
||||
// Stream flag
|
||||
Stream bool
|
||||
}
|
||||
|
||||
// Service represents an API service
|
||||
|
132
api/grpc_test.go
Normal file
132
api/grpc_test.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package api_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
ahandler "github.com/micro/go-micro/v2/api/handler"
|
||||
apirpc "github.com/micro/go-micro/v2/api/handler/rpc"
|
||||
"github.com/micro/go-micro/v2/api/router"
|
||||
rstatic "github.com/micro/go-micro/v2/api/router/static"
|
||||
bmemory "github.com/micro/go-micro/v2/broker/memory"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
gcli "github.com/micro/go-micro/v2/client/grpc"
|
||||
rmemory "github.com/micro/go-micro/v2/registry/memory"
|
||||
"github.com/micro/go-micro/v2/server"
|
||||
gsrv "github.com/micro/go-micro/v2/server/grpc"
|
||||
tgrpc "github.com/micro/go-micro/v2/transport/grpc"
|
||||
|
||||
pb "github.com/micro/go-micro/v2/server/grpc/proto"
|
||||
)
|
||||
|
||||
// server is used to implement helloworld.GreeterServer.
|
||||
type testServer struct {
|
||||
msgCount int
|
||||
}
|
||||
|
||||
// TestHello implements helloworld.GreeterServer
|
||||
func (s *testServer) Call(ctx context.Context, req *pb.Request, rsp *pb.Response) error {
|
||||
rsp.Msg = "Hello " + req.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestApiAndGRPC(t *testing.T) {
|
||||
r := rmemory.NewRegistry()
|
||||
b := bmemory.NewBroker()
|
||||
tr := tgrpc.NewTransport()
|
||||
s := gsrv.NewServer(
|
||||
server.Broker(b),
|
||||
server.Name("foo"),
|
||||
server.Registry(r),
|
||||
server.Transport(tr),
|
||||
)
|
||||
c := gcli.NewClient(
|
||||
client.Registry(r),
|
||||
client.Broker(b),
|
||||
client.Transport(tr),
|
||||
)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
svc := micro.NewService(
|
||||
micro.Server(s),
|
||||
micro.Client(c),
|
||||
micro.Broker(b),
|
||||
micro.Registry(r),
|
||||
micro.Transport(tr),
|
||||
micro.Context(ctx))
|
||||
h := &testServer{}
|
||||
pb.RegisterTestHandler(s, h)
|
||||
|
||||
go func() {
|
||||
if err := svc.Run(); err != nil {
|
||||
t.Fatalf("failed to start: %v", err)
|
||||
}
|
||||
}()
|
||||
time.Sleep(1 * time.Second)
|
||||
// check registration
|
||||
services, err := r.GetService("foo")
|
||||
if err != nil || len(services) == 0 {
|
||||
t.Fatalf("failed to get service: %v # %d", err, len(services))
|
||||
}
|
||||
|
||||
router := rstatic.NewRouter(
|
||||
router.WithHandler(apirpc.Handler),
|
||||
router.WithRegistry(svc.Server().Options().Registry),
|
||||
)
|
||||
err = router.Register(&api.Endpoint{
|
||||
Name: "foo.Test.Call",
|
||||
Method: []string{"GET"},
|
||||
Path: []string{"/api/v0/test/call/{name}"},
|
||||
Handler: "rpc",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hrpc := apirpc.NewHandler(
|
||||
ahandler.WithService(svc),
|
||||
ahandler.WithRouter(router),
|
||||
)
|
||||
|
||||
hsrv := &http.Server{
|
||||
Handler: hrpc,
|
||||
Addr: "127.0.0.1:6543",
|
||||
WriteTimeout: 15 * time.Second,
|
||||
ReadTimeout: 15 * time.Second,
|
||||
IdleTimeout: 20 * time.Second,
|
||||
MaxHeaderBytes: 1024 * 1024 * 1, // 1Mb
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Println(hsrv.ListenAndServe())
|
||||
}()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
rsp, err := http.Get(fmt.Sprintf("http://%s/api/v0/test/call/TEST", hsrv.Addr))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to created http.Request: %v", err)
|
||||
}
|
||||
defer rsp.Body.Close()
|
||||
buf, err := ioutil.ReadAll(rsp.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
jsonMsg := `{"msg":"Hello TEST"}`
|
||||
if string(buf) != jsonMsg {
|
||||
t.Fatalf("invalid message received, parsing error %s != %s", buf, jsonMsg)
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
||||
}
|
@@ -24,6 +24,12 @@ const (
|
||||
|
||||
// API handler is the default handler which takes api.Request and returns api.Response
|
||||
func (a *apiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
bsize := handler.DefaultMaxRecvSize
|
||||
if a.opts.MaxRecvSize > 0 {
|
||||
bsize = a.opts.MaxRecvSize
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, bsize)
|
||||
request, err := requestToProto(r)
|
||||
if err != nil {
|
||||
er := errors.InternalServerError("go.micro.api", err.Error())
|
||||
|
@@ -2,7 +2,6 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -11,6 +10,12 @@ import (
|
||||
api "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/oxtoacart/bpool"
|
||||
)
|
||||
|
||||
var (
|
||||
// need to calculate later to specify useful defaults
|
||||
bufferPool = bpool.NewSizedBufferPool(1024, 8)
|
||||
)
|
||||
|
||||
func requestToProto(r *http.Request) (*api.Request, error) {
|
||||
@@ -39,9 +44,12 @@ func requestToProto(r *http.Request) (*api.Request, error) {
|
||||
case "application/x-www-form-urlencoded":
|
||||
// expect form vals in Post data
|
||||
default:
|
||||
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
req.Body = string(data)
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
if _, err = buf.ReadFrom(r.Body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Body = buf.String()
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,6 @@ package broker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -14,7 +13,12 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"github.com/oxtoacart/bpool"
|
||||
)
|
||||
|
||||
var (
|
||||
bufferPool = bpool.NewSizedBufferPool(1024, 8)
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -136,7 +140,9 @@ func (c *conn) writeLoop() {
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -153,6 +159,13 @@ func (c *conn) writeLoop() {
|
||||
}
|
||||
|
||||
func (b *brokerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
bsize := handler.DefaultMaxRecvSize
|
||||
if b.opts.MaxRecvSize > 0 {
|
||||
bsize = b.opts.MaxRecvSize
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, bsize)
|
||||
|
||||
br := b.opts.Service.Client().Options().Broker
|
||||
|
||||
// Setup the broker
|
||||
@@ -189,14 +202,15 @@ func (b *brokerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Read body
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
if _, err := buf.ReadFrom(r.Body); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
// Set body
|
||||
msg.Body = b
|
||||
msg.Body = buf.Bytes()
|
||||
// Set body
|
||||
|
||||
// Publish
|
||||
br.Publish(topic, msg)
|
||||
@@ -214,7 +228,9 @@ func (b *brokerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ws, err := b.u.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
type event struct {
|
||||
options handler.Options
|
||||
opts handler.Options
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -58,10 +58,17 @@ func evRoute(ns, p string) (string, string) {
|
||||
}
|
||||
|
||||
func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
bsize := handler.DefaultMaxRecvSize
|
||||
if e.opts.MaxRecvSize > 0 {
|
||||
bsize = e.opts.MaxRecvSize
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, bsize)
|
||||
|
||||
// request to topic:event
|
||||
// create event
|
||||
// publish to topic
|
||||
topic, _ := evRoute(e.options.Namespace, r.URL.Path)
|
||||
topic, _ := evRoute(e.opts.Namespace, r.URL.Path)
|
||||
|
||||
// create event
|
||||
ev, err := FromRequest(r)
|
||||
@@ -71,7 +78,7 @@ func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// get client
|
||||
c := e.options.Service.Client()
|
||||
c := e.opts.Service.Client()
|
||||
|
||||
// create publication
|
||||
p := c.NewMessage(topic, ev)
|
||||
@@ -89,6 +96,6 @@ func (e *event) String() string {
|
||||
|
||||
func NewHandler(opts ...handler.Option) handler.Handler {
|
||||
return &event{
|
||||
options: handler.NewOptions(opts...),
|
||||
opts: handler.NewOptions(opts...),
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -32,9 +31,14 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/oxtoacart/bpool"
|
||||
validator "gopkg.in/go-playground/validator.v9"
|
||||
)
|
||||
|
||||
var (
|
||||
bufferPool = bpool.NewSizedBufferPool(1024, 8)
|
||||
)
|
||||
|
||||
const (
|
||||
// TransformationVersion is indicative of the revision of how Event Gateway transforms a request into CloudEvents format.
|
||||
TransformationVersion = "0.1"
|
||||
@@ -97,10 +101,12 @@ func FromRequest(r *http.Request) (*Event, error) {
|
||||
// Read request body
|
||||
body := []byte{}
|
||||
if r.Body != nil {
|
||||
body, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
if _, err := buf.ReadFrom(r.Body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body = buf.Bytes()
|
||||
}
|
||||
|
||||
var event *Event
|
||||
|
@@ -4,7 +4,6 @@ package event
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"regexp"
|
||||
@@ -15,10 +14,15 @@ import (
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
proto "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/util/ctx"
|
||||
"github.com/oxtoacart/bpool"
|
||||
)
|
||||
|
||||
var (
|
||||
bufferPool = bpool.NewSizedBufferPool(1024, 8)
|
||||
)
|
||||
|
||||
type event struct {
|
||||
options handler.Options
|
||||
opts handler.Options
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -64,11 +68,18 @@ func evRoute(ns, p string) (string, string) {
|
||||
}
|
||||
|
||||
func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
bsize := handler.DefaultMaxRecvSize
|
||||
if e.opts.MaxRecvSize > 0 {
|
||||
bsize = e.opts.MaxRecvSize
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, bsize)
|
||||
|
||||
// request to topic:event
|
||||
// create event
|
||||
// publish to topic
|
||||
|
||||
topic, action := evRoute(e.options.Namespace, r.URL.Path)
|
||||
topic, action := evRoute(e.opts.Namespace, r.URL.Path)
|
||||
|
||||
// create event
|
||||
ev := &proto.Event{
|
||||
@@ -96,16 +107,18 @@ func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
bytes, _ := json.Marshal(r.URL.Query())
|
||||
ev.Data = string(bytes)
|
||||
} else {
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
// Read body
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
if _, err := buf.ReadFrom(r.Body); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
ev.Data = string(b)
|
||||
ev.Data = buf.String()
|
||||
}
|
||||
|
||||
// get client
|
||||
c := e.options.Service.Client()
|
||||
c := e.opts.Service.Client()
|
||||
|
||||
// create publication
|
||||
p := c.NewMessage(topic, ev)
|
||||
@@ -123,6 +136,6 @@ func (e *event) String() string {
|
||||
|
||||
func NewHandler(opts ...handler.Option) handler.Handler {
|
||||
return &event{
|
||||
options: handler.NewOptions(opts...),
|
||||
opts: handler.NewOptions(opts...),
|
||||
}
|
||||
}
|
||||
|
@@ -5,10 +5,15 @@ import (
|
||||
"github.com/micro/go-micro/v2/api/router"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultMaxRecvSize int64 = 1024 * 1024 * 100 // 10Mb
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Namespace string
|
||||
Router router.Router
|
||||
Service micro.Service
|
||||
MaxRecvSize int64
|
||||
Namespace string
|
||||
Router router.Router
|
||||
Service micro.Service
|
||||
}
|
||||
|
||||
type Option func(o *Options)
|
||||
@@ -30,6 +35,10 @@ func NewOptions(opts ...Option) Options {
|
||||
WithNamespace("go.micro.api")(&options)
|
||||
}
|
||||
|
||||
if options.MaxRecvSize == 0 {
|
||||
options.MaxRecvSize = DefaultMaxRecvSize
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
@@ -53,3 +62,10 @@ func WithService(s micro.Service) Option {
|
||||
o.Service = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithmaxRecvSize specifies max body size
|
||||
func WithMaxRecvSize(size int64) Option {
|
||||
return func(o *Options) {
|
||||
o.MaxRecvSize = size
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package registry
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -11,6 +10,11 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/oxtoacart/bpool"
|
||||
)
|
||||
|
||||
var (
|
||||
bufferPool = bpool.NewSizedBufferPool(1024, 8)
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,12 +33,15 @@ type registryHandler struct {
|
||||
|
||||
func (rh *registryHandler) add(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
defer r.Body.Close()
|
||||
|
||||
// Read body
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
if _, err := buf.ReadFrom(r.Body); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
var opts []registry.RegisterOption
|
||||
|
||||
@@ -47,13 +54,11 @@ func (rh *registryHandler) add(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
var service *registry.Service
|
||||
err = json.Unmarshal(b, &service)
|
||||
if err != nil {
|
||||
if err := json.NewDecoder(buf).Decode(&service); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
err = rh.reg.Register(service, opts...)
|
||||
if err != nil {
|
||||
if err := rh.reg.Register(service, opts...); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
@@ -61,21 +66,22 @@ func (rh *registryHandler) add(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (rh *registryHandler) del(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
var service *registry.Service
|
||||
err = json.Unmarshal(b, &service)
|
||||
if err != nil {
|
||||
// Read body
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
if _, err := buf.ReadFrom(r.Body); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
err = rh.reg.Deregister(service)
|
||||
if err != nil {
|
||||
|
||||
var service *registry.Service
|
||||
if err := json.NewDecoder(buf).Decode(&service); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
if err := rh.reg.Deregister(service); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
@@ -187,6 +193,13 @@ func watch(rw registry.Watcher, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (rh *registryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
bsize := handler.DefaultMaxRecvSize
|
||||
if rh.opts.MaxRecvSize > 0 {
|
||||
bsize = rh.opts.MaxRecvSize
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, bsize)
|
||||
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
rh.get(w, r)
|
||||
|
@@ -4,23 +4,26 @@ package rpc
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
"github.com/joncalhoun/qson"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
proto "github.com/micro/go-micro/v2/api/internal/proto"
|
||||
"github.com/micro/go-micro/v2/api/internal/proto"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/codec/jsonrpc"
|
||||
"github.com/micro/go-micro/v2/codec/protorpc"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/util/ctx"
|
||||
"github.com/oxtoacart/bpool"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -44,6 +47,8 @@ var (
|
||||
"application/proto-rpc",
|
||||
"application/octet-stream",
|
||||
}
|
||||
|
||||
bufferPool = bpool.NewSizedBufferPool(1024, 8)
|
||||
)
|
||||
|
||||
type rpcHandler struct {
|
||||
@@ -68,6 +73,13 @@ func strategy(services []*registry.Service) selector.Strategy {
|
||||
}
|
||||
|
||||
func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
bsize := handler.DefaultMaxRecvSize
|
||||
if h.opts.MaxRecvSize > 0 {
|
||||
bsize = h.opts.MaxRecvSize
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, bsize)
|
||||
|
||||
defer r.Body.Close()
|
||||
var service *api.Service
|
||||
|
||||
@@ -90,7 +102,7 @@ func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// only allow post when we have the router
|
||||
if r.Method != "GET" && (h.opts.Router != nil && r.Method != "POST") {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
writeError(w, r, errors.MethodNotAllowed("go.micro.api", "method not allowed"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -104,9 +116,19 @@ func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// micro client
|
||||
c := h.opts.Service.Client()
|
||||
|
||||
// create context
|
||||
cx := ctx.FromRequest(r)
|
||||
|
||||
// if stream we currently only support json
|
||||
if isStream(r, service) {
|
||||
serveWebsocket(cx, w, r, service, c)
|
||||
return
|
||||
}
|
||||
|
||||
// create strategy
|
||||
so := selector.WithStrategy(strategy(service.Services))
|
||||
|
||||
// walk the standard call path
|
||||
// get payload
|
||||
br, err := requestPayload(r)
|
||||
if err != nil {
|
||||
@@ -114,9 +136,6 @@ func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// create context
|
||||
cx := ctx.FromRequest(r)
|
||||
|
||||
var rsp []byte
|
||||
|
||||
switch {
|
||||
@@ -145,7 +164,12 @@ func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// marshall response
|
||||
rsp, _ = response.Marshal()
|
||||
rsp, err = response.Marshal()
|
||||
if err != nil {
|
||||
writeError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
default:
|
||||
// if json codec is not present set to json
|
||||
if !hasCodec(ct, jsonCodecs) {
|
||||
@@ -176,7 +200,11 @@ func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// marshall response
|
||||
rsp, _ = response.MarshalJSON()
|
||||
rsp, err = response.MarshalJSON()
|
||||
if err != nil {
|
||||
writeError(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// write the response
|
||||
@@ -200,8 +228,11 @@ func hasCodec(ct string, codecs []string) bool {
|
||||
// If the request is a GET the query string parameters are extracted and marshaled to JSON and the raw bytes are returned.
|
||||
// If the request method is a POST the request body is read and returned
|
||||
func requestPayload(r *http.Request) ([]byte, error) {
|
||||
var err error
|
||||
|
||||
// we have to decode json-rpc and proto-rpc because we suck
|
||||
// well actually because there's no proxy codec right now
|
||||
|
||||
ct := r.Header.Get("Content-Type")
|
||||
switch {
|
||||
case strings.Contains(ct, "application/json-rpc"):
|
||||
@@ -210,11 +241,11 @@ func requestPayload(r *http.Request) ([]byte, error) {
|
||||
Header: make(map[string]string),
|
||||
}
|
||||
c := jsonrpc.NewCodec(&buffer{r.Body})
|
||||
if err := c.ReadHeader(&msg, codec.Request); err != nil {
|
||||
if err = c.ReadHeader(&msg, codec.Request); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var raw json.RawMessage
|
||||
if err := c.ReadBody(&raw); err != nil {
|
||||
if err = c.ReadBody(&raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ([]byte)(raw), nil
|
||||
@@ -224,15 +255,14 @@ func requestPayload(r *http.Request) ([]byte, error) {
|
||||
Header: make(map[string]string),
|
||||
}
|
||||
c := protorpc.NewCodec(&buffer{r.Body})
|
||||
if err := c.ReadHeader(&msg, codec.Request); err != nil {
|
||||
if err = c.ReadHeader(&msg, codec.Request); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var raw proto.Message
|
||||
if err := c.ReadBody(&raw); err != nil {
|
||||
if err = c.ReadBody(&raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, _ := raw.Marshal()
|
||||
return b, nil
|
||||
return raw.Marshal()
|
||||
case strings.Contains(ct, "application/www-x-form-urlencoded"):
|
||||
r.ParseForm()
|
||||
|
||||
@@ -243,20 +273,95 @@ func requestPayload(r *http.Request) ([]byte, error) {
|
||||
}
|
||||
|
||||
// marshal
|
||||
b, _ := json.Marshal(vals)
|
||||
return b, nil
|
||||
return json.Marshal(vals)
|
||||
// TODO: application/grpc
|
||||
}
|
||||
|
||||
// otherwise as per usual
|
||||
ctx := r.Context()
|
||||
// dont user meadata.FromContext as it mangles names
|
||||
md, ok := ctx.Value(metadata.MetadataKey{}).(metadata.Metadata)
|
||||
if !ok {
|
||||
md = make(map[string]string)
|
||||
}
|
||||
// allocate maximum
|
||||
matches := make(map[string]string, len(md))
|
||||
for k, v := range md {
|
||||
if strings.HasPrefix(k, "x-api-field-") {
|
||||
matches[strings.TrimPrefix(k, "x-api-field-")] = v
|
||||
}
|
||||
delete(md, k)
|
||||
}
|
||||
|
||||
// restore context without fields
|
||||
ctx = metadata.NewContext(ctx, md)
|
||||
*r = *r.WithContext(ctx)
|
||||
req := make(map[string]interface{}, len(md))
|
||||
for k, v := range matches {
|
||||
ps := strings.Split(k, ".")
|
||||
if len(ps) == 1 {
|
||||
req[k] = v
|
||||
continue
|
||||
}
|
||||
|
||||
em := make(map[string]interface{})
|
||||
em[ps[len(ps)-1]] = v
|
||||
for i := len(ps) - 2; i > 0; i-- {
|
||||
nm := make(map[string]interface{})
|
||||
nm[ps[i]] = em
|
||||
em = nm
|
||||
}
|
||||
req[ps[0]] = em
|
||||
}
|
||||
pathbuf := []byte("{}")
|
||||
if len(req) > 0 {
|
||||
pathbuf, err = json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
urlbuf := []byte("{}")
|
||||
if len(r.URL.RawQuery) > 0 {
|
||||
urlbuf, err = qson.ToJSON(r.URL.RawQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out, err := jsonpatch.MergeMergePatches(urlbuf, pathbuf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
if len(r.URL.RawQuery) > 0 {
|
||||
return qson.ToJSON(r.URL.RawQuery)
|
||||
// empty response
|
||||
if strings.Contains(ct, "application/json") && string(out) == "{}" {
|
||||
return out, nil
|
||||
} else if string(out) == "{}" && !strings.Contains(ct, "application/json") {
|
||||
return []byte{}, nil
|
||||
}
|
||||
case "PATCH", "POST":
|
||||
return ioutil.ReadAll(r.Body)
|
||||
return out, nil
|
||||
case "PATCH", "POST", "PUT", "DELETE":
|
||||
bodybuf := []byte("{}")
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
if _, err := buf.ReadFrom(r.Body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if b := buf.Bytes(); len(b) > 0 {
|
||||
bodybuf = b
|
||||
} else {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
if out, err = jsonpatch.MergeMergePatches(out, bodybuf); err == nil {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
//fallback to previous unknown behaviour
|
||||
return bodybuf, nil
|
||||
|
||||
}
|
||||
|
||||
return []byte{}, nil
|
||||
@@ -288,7 +393,12 @@ func writeError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
w.Header().Set("grpc-message", ce.Detail)
|
||||
}
|
||||
|
||||
w.Write([]byte(ce.Error()))
|
||||
_, werr := w.Write([]byte(ce.Error()))
|
||||
if werr != nil {
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(werr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writeResponse(w http.ResponseWriter, r *http.Request, rsp []byte) {
|
||||
@@ -303,8 +413,19 @@ func writeResponse(w http.ResponseWriter, r *http.Request, rsp []byte) {
|
||||
w.Header().Set("grpc-message", "")
|
||||
}
|
||||
|
||||
// write 204 status if rsp is nil
|
||||
if len(rsp) == 0 {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// write response
|
||||
w.Write(rsp)
|
||||
_, err := w.Write(rsp)
|
||||
if err != nil {
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func NewHandler(opts ...handler.Option) handler.Handler {
|
||||
|
@@ -27,6 +27,23 @@ func TestRequestPayloadFromRequest(t *testing.T) {
|
||||
t.Fatal("Failed to marshal proto to JSON ", err)
|
||||
}
|
||||
|
||||
jsonUrlBytes := []byte(`{"key1":"val1","key2":"val2","name":"Test"}`)
|
||||
|
||||
t.Run("extracting a json from a POST request with url params", func(t *testing.T) {
|
||||
r, err := http.NewRequest("POST", "http://localhost/my/path?key1=val1&key2=val2", bytes.NewReader(jsonBytes))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to created http.Request: %v", err)
|
||||
}
|
||||
|
||||
extByte, err := requestPayload(r)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to extract payload from request: %v", err)
|
||||
}
|
||||
if string(extByte) != string(jsonUrlBytes) {
|
||||
t.Fatalf("Expected %v and %v to match", string(extByte), jsonUrlBytes)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("extracting a proto from a POST request", func(t *testing.T) {
|
||||
r, err := http.NewRequest("POST", "http://localhost/my/path", bytes.NewReader(protoBytes))
|
||||
if err != nil {
|
||||
|
150
api/handler/rpc/stream.go
Normal file
150
api/handler/rpc/stream.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
// serveWebsocket will stream rpc back over websockets assuming json
|
||||
func serveWebsocket(ctx context.Context, w http.ResponseWriter, r *http.Request, service *api.Service, c client.Client) {
|
||||
// upgrade the connection
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// close on exit
|
||||
defer conn.Close()
|
||||
|
||||
// wait for the first request so we know
|
||||
_, p, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// send to backend
|
||||
// default to trying json
|
||||
var request json.RawMessage
|
||||
// if the extracted payload isn't empty lets use it
|
||||
if len(p) > 0 {
|
||||
request = json.RawMessage(p)
|
||||
}
|
||||
|
||||
// create a request to the backend
|
||||
req := c.NewRequest(
|
||||
service.Name,
|
||||
service.Endpoint.Name,
|
||||
&request,
|
||||
client.WithContentType("application/json"),
|
||||
)
|
||||
|
||||
so := selector.WithStrategy(strategy(service.Services))
|
||||
|
||||
// create a new stream
|
||||
stream, err := c.Stream(ctx, req, client.WithSelectOption(so))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// send the first request for the client
|
||||
// since
|
||||
if err := stream.Send(request); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
go writeLoop(conn, stream)
|
||||
|
||||
resp := stream.Response()
|
||||
|
||||
// receive from stream and send to client
|
||||
for {
|
||||
// read backend response body
|
||||
body, err := resp.Read()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// write the response
|
||||
if err := conn.WriteMessage(websocket.TextMessage, body); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writeLoop
|
||||
func writeLoop(conn *websocket.Conn, stream client.Stream) {
|
||||
// close stream when done
|
||||
defer stream.Close()
|
||||
|
||||
for {
|
||||
_, p, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// send to backend
|
||||
// default to trying json
|
||||
var request json.RawMessage
|
||||
// if the extracted payload isn't empty lets use it
|
||||
if len(p) > 0 {
|
||||
request = json.RawMessage(p)
|
||||
}
|
||||
|
||||
if err := stream.Send(request); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isStream(r *http.Request, srv *api.Service) bool {
|
||||
// check if it's a web socket
|
||||
if !isWebSocket(r) {
|
||||
return false
|
||||
}
|
||||
|
||||
// check if the endpoint supports streaming
|
||||
for _, service := range srv.Services {
|
||||
for _, ep := range service.Endpoints {
|
||||
// skip if it doesn't match the name
|
||||
if ep.Name != srv.Endpoint.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
// matched if the name
|
||||
if v := ep.Metadata["stream"]; v == "true" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func isWebSocket(r *http.Request) bool {
|
||||
contains := func(key, val string) bool {
|
||||
vv := strings.Split(r.Header.Get(key), ",")
|
||||
for _, v := range vv {
|
||||
if val == strings.ToLower(strings.TrimSpace(v)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if contains("Connection", "upgrade") && contains("Upgrade", "websocket") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/v2/api/proto/api.proto
|
||||
// source: api/proto/api.proto
|
||||
|
||||
package go_api
|
||||
|
||||
@@ -32,7 +32,7 @@ func (m *Pair) Reset() { *m = Pair{} }
|
||||
func (m *Pair) String() string { return proto.CompactTextString(m) }
|
||||
func (*Pair) ProtoMessage() {}
|
||||
func (*Pair) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7b6696ef87ec1943, []int{0}
|
||||
return fileDescriptor_2df576b66d12087a, []int{0}
|
||||
}
|
||||
|
||||
func (m *Pair) XXX_Unmarshal(b []byte) error {
|
||||
@@ -86,7 +86,7 @@ func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7b6696ef87ec1943, []int{1}
|
||||
return fileDescriptor_2df576b66d12087a, []int{1}
|
||||
}
|
||||
|
||||
func (m *Request) XXX_Unmarshal(b []byte) error {
|
||||
@@ -171,7 +171,7 @@ func (m *Response) Reset() { *m = Response{} }
|
||||
func (m *Response) String() string { return proto.CompactTextString(m) }
|
||||
func (*Response) ProtoMessage() {}
|
||||
func (*Response) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7b6696ef87ec1943, []int{2}
|
||||
return fileDescriptor_2df576b66d12087a, []int{2}
|
||||
}
|
||||
|
||||
func (m *Response) XXX_Unmarshal(b []byte) error {
|
||||
@@ -235,7 +235,7 @@ func (m *Event) Reset() { *m = Event{} }
|
||||
func (m *Event) String() string { return proto.CompactTextString(m) }
|
||||
func (*Event) ProtoMessage() {}
|
||||
func (*Event) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7b6696ef87ec1943, []int{3}
|
||||
return fileDescriptor_2df576b66d12087a, []int{3}
|
||||
}
|
||||
|
||||
func (m *Event) XXX_Unmarshal(b []byte) error {
|
||||
@@ -303,36 +303,33 @@ func init() {
|
||||
proto.RegisterMapType((map[string]*Pair)(nil), "go.api.Event.HeaderEntry")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/go-micro/v2/api/proto/api.proto", fileDescriptor_7b6696ef87ec1943)
|
||||
}
|
||||
func init() { proto.RegisterFile("api/proto/api.proto", fileDescriptor_2df576b66d12087a) }
|
||||
|
||||
var fileDescriptor_7b6696ef87ec1943 = []byte{
|
||||
// 408 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0x4d, 0x8f, 0xd3, 0x30,
|
||||
0x10, 0x55, 0xe2, 0x24, 0xbb, 0x99, 0x22, 0x84, 0x7c, 0x40, 0x66, 0x59, 0xa1, 0x2a, 0xa7, 0x0a,
|
||||
0xa9, 0x29, 0xec, 0x72, 0x40, 0x5c, 0xa1, 0x5a, 0x8e, 0x2b, 0xff, 0x03, 0x77, 0x63, 0x25, 0x16,
|
||||
0x4d, 0x1c, 0x62, 0xa7, 0x52, 0x7f, 0x1c, 0x07, 0x7e, 0x06, 0xff, 0x06, 0x79, 0xec, 0x7e, 0x50,
|
||||
0x95, 0x0b, 0xf4, 0xf6, 0x62, 0xbf, 0x79, 0xf3, 0xe6, 0x8d, 0x03, 0xf3, 0x5a, 0xd9, 0x66, 0x5c,
|
||||
0x95, 0x4f, 0xba, 0x5d, 0xb4, 0xea, 0x69, 0xd0, 0x8b, 0x5a, 0xcf, 0x3d, 0x10, 0xbd, 0x5a, 0xf4,
|
||||
0x83, 0xb6, 0x88, 0x4a, 0x44, 0x34, 0xab, 0x75, 0x29, 0x7a, 0x55, 0xbc, 0x83, 0xe4, 0x51, 0xa8,
|
||||
0x81, 0xbe, 0x00, 0xf2, 0x4d, 0x6e, 0x59, 0x34, 0x8d, 0x66, 0x39, 0x77, 0x90, 0xbe, 0x84, 0x6c,
|
||||
0x23, 0xd6, 0xa3, 0x34, 0x2c, 0x9e, 0x92, 0x59, 0xce, 0xc3, 0x57, 0xf1, 0x93, 0xc0, 0x15, 0x97,
|
||||
0xdf, 0x47, 0x69, 0xac, 0xe3, 0xb4, 0xd2, 0x36, 0xba, 0x0a, 0x85, 0xe1, 0x8b, 0x52, 0x48, 0x7a,
|
||||
0x61, 0x1b, 0x16, 0xe3, 0x29, 0x62, 0x7a, 0x0f, 0x59, 0x23, 0x45, 0x25, 0x07, 0x46, 0xa6, 0x64,
|
||||
0x36, 0xb9, 0x7b, 0x5d, 0x7a, 0x0b, 0x65, 0x10, 0x2b, 0xbf, 0xe2, 0xed, 0xb2, 0xb3, 0xc3, 0x96,
|
||||
0x07, 0x2a, 0x7d, 0x0b, 0xa4, 0x96, 0x96, 0x25, 0x58, 0xc1, 0x4e, 0x2b, 0x1e, 0xa4, 0xf5, 0x74,
|
||||
0x47, 0xa2, 0x73, 0x48, 0x7a, 0x6d, 0x2c, 0x4b, 0x91, 0xfc, 0xea, 0x94, 0xfc, 0xa8, 0x4d, 0x60,
|
||||
0x23, 0xcd, 0x79, 0x5c, 0xe9, 0x6a, 0xcb, 0x32, 0xef, 0xd1, 0x61, 0x97, 0xc2, 0x38, 0xac, 0xd9,
|
||||
0x95, 0x4f, 0x61, 0x1c, 0xd6, 0x37, 0x0f, 0x30, 0x39, 0xf2, 0x75, 0x26, 0xa6, 0x02, 0x52, 0x0c,
|
||||
0x06, 0x67, 0x9d, 0xdc, 0x3d, 0xdb, 0xb5, 0x75, 0xa9, 0x72, 0x7f, 0xf5, 0x29, 0xfe, 0x18, 0xdd,
|
||||
0x7c, 0x81, 0xeb, 0x9d, 0xdd, 0xff, 0x50, 0x59, 0x42, 0xbe, 0x9f, 0xe3, 0xdf, 0x65, 0x8a, 0x1f,
|
||||
0x11, 0x5c, 0x73, 0x69, 0x7a, 0xdd, 0x19, 0x49, 0xdf, 0x00, 0x18, 0x2b, 0xec, 0x68, 0x3e, 0xeb,
|
||||
0x4a, 0xa2, 0x5a, 0xca, 0x8f, 0x4e, 0xe8, 0x87, 0xfd, 0xe2, 0x62, 0x4c, 0xf6, 0xf6, 0x90, 0xac,
|
||||
0x57, 0x38, 0xbb, 0xb9, 0x5d, 0xbc, 0xe4, 0x10, 0xef, 0xc5, 0xc2, 0x2c, 0x7e, 0x45, 0x90, 0x2e,
|
||||
0x37, 0xb2, 0xc3, 0x2d, 0x76, 0xa2, 0x95, 0x41, 0x04, 0x31, 0x7d, 0x0e, 0xb1, 0xaa, 0xc2, 0xdb,
|
||||
0x8b, 0x55, 0x45, 0x6f, 0x21, 0xb7, 0xaa, 0x95, 0xc6, 0x8a, 0xb6, 0x47, 0x3f, 0x84, 0x1f, 0x0e,
|
||||
0xe8, 0xfb, 0xfd, 0x78, 0xc9, 0x9f, 0x0f, 0x07, 0x1b, 0xfc, 0x6d, 0xb6, 0x4a, 0x58, 0xc1, 0x52,
|
||||
0xdf, 0xd4, 0xe1, 0x8b, 0xcd, 0xb6, 0xca, 0xf0, 0x07, 0xbd, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff,
|
||||
0x97, 0xf3, 0x59, 0x6e, 0xd1, 0x03, 0x00, 0x00,
|
||||
var fileDescriptor_2df576b66d12087a = []byte{
|
||||
// 393 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0xcd, 0xce, 0xd3, 0x30,
|
||||
0x10, 0x54, 0xe2, 0x24, 0x6d, 0xb6, 0x08, 0x21, 0x23, 0x21, 0x53, 0x2a, 0x54, 0xe5, 0x54, 0x21,
|
||||
0x91, 0x42, 0xcb, 0x01, 0x71, 0x85, 0xaa, 0x1c, 0x2b, 0xbf, 0x81, 0xab, 0x58, 0x6d, 0x44, 0x13,
|
||||
0x9b, 0xd8, 0xa9, 0xd4, 0x87, 0xe3, 0xc0, 0x63, 0xf0, 0x36, 0xc8, 0x1b, 0xf7, 0xe7, 0xab, 0xfa,
|
||||
0x5d, 0xbe, 0xaf, 0xb7, 0x89, 0x3d, 0x3b, 0x3b, 0x3b, 0xeb, 0xc0, 0x6b, 0xa1, 0xcb, 0xa9, 0x6e,
|
||||
0x94, 0x55, 0x53, 0xa1, 0xcb, 0x1c, 0x11, 0x4d, 0x36, 0x2a, 0x17, 0xba, 0xcc, 0x3e, 0x41, 0xb4,
|
||||
0x12, 0x65, 0x43, 0x5f, 0x01, 0xf9, 0x25, 0x0f, 0x2c, 0x18, 0x07, 0x93, 0x94, 0x3b, 0x48, 0xdf,
|
||||
0x40, 0xb2, 0x17, 0xbb, 0x56, 0x1a, 0x16, 0x8e, 0xc9, 0x24, 0xe5, 0xfe, 0x2b, 0xfb, 0x4b, 0xa0,
|
||||
0xc7, 0xe5, 0xef, 0x56, 0x1a, 0xeb, 0x38, 0x95, 0xb4, 0x5b, 0x55, 0xf8, 0x42, 0xff, 0x45, 0x29,
|
||||
0x44, 0x5a, 0xd8, 0x2d, 0x0b, 0xf1, 0x14, 0x31, 0x9d, 0x43, 0xb2, 0x95, 0xa2, 0x90, 0x0d, 0x23,
|
||||
0x63, 0x32, 0x19, 0xcc, 0xde, 0xe5, 0x9d, 0x85, 0xdc, 0x8b, 0xe5, 0x3f, 0xf1, 0x76, 0x51, 0xdb,
|
||||
0xe6, 0xc0, 0x3d, 0x95, 0x7e, 0x00, 0xb2, 0x91, 0x96, 0x45, 0x58, 0xc1, 0xae, 0x2b, 0x96, 0xd2,
|
||||
0x76, 0x74, 0x47, 0xa2, 0x1f, 0x21, 0xd2, 0xca, 0x58, 0x16, 0x23, 0xf9, 0xed, 0x35, 0x79, 0xa5,
|
||||
0x8c, 0x67, 0x23, 0xcd, 0x79, 0x5c, 0xab, 0xe2, 0xc0, 0x92, 0xce, 0xa3, 0xc3, 0x2e, 0x85, 0xb6,
|
||||
0xd9, 0xb1, 0x5e, 0x97, 0x42, 0xdb, 0xec, 0x86, 0x4b, 0x18, 0x5c, 0xf8, 0xba, 0x11, 0x53, 0x06,
|
||||
0x31, 0x06, 0x83, 0xb3, 0x0e, 0x66, 0x2f, 0x8e, 0x6d, 0x5d, 0xaa, 0xbc, 0xbb, 0xfa, 0x16, 0x7e,
|
||||
0x0d, 0x86, 0x3f, 0xa0, 0x7f, 0xb4, 0xfb, 0x0c, 0x95, 0x05, 0xa4, 0xa7, 0x39, 0x9e, 0x2e, 0x93,
|
||||
0xfd, 0x09, 0xa0, 0xcf, 0xa5, 0xd1, 0xaa, 0x36, 0x92, 0xbe, 0x07, 0x30, 0x56, 0xd8, 0xd6, 0x7c,
|
||||
0x57, 0x85, 0x44, 0xb5, 0x98, 0x5f, 0x9c, 0xd0, 0x2f, 0xa7, 0xc5, 0x85, 0x98, 0xec, 0xe8, 0x9c,
|
||||
0x6c, 0xa7, 0x70, 0x73, 0x73, 0xc7, 0x78, 0xc9, 0x39, 0xde, 0xbb, 0x85, 0x99, 0xfd, 0x0b, 0x20,
|
||||
0x5e, 0xec, 0x65, 0x8d, 0x5b, 0xac, 0x45, 0x25, 0xbd, 0x08, 0x62, 0xfa, 0x12, 0xc2, 0xb2, 0xf0,
|
||||
0x6f, 0x2f, 0x2c, 0x0b, 0x3a, 0x82, 0xd4, 0x96, 0x95, 0x34, 0x56, 0x54, 0x1a, 0xfd, 0x10, 0x7e,
|
||||
0x3e, 0xa0, 0x9f, 0x4f, 0xe3, 0x45, 0x0f, 0x1f, 0x0e, 0x36, 0x78, 0x6c, 0xb6, 0x42, 0x58, 0xc1,
|
||||
0xe2, 0xae, 0xa9, 0xc3, 0x77, 0x9b, 0x6d, 0x9d, 0xe0, 0x0f, 0x3a, 0xff, 0x1f, 0x00, 0x00, 0xff,
|
||||
0xff, 0xd4, 0x6d, 0x70, 0x51, 0xb7, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/v2/api/proto/api.proto
|
||||
// source: api/proto/api.proto
|
||||
|
||||
package go_api
|
||||
|
||||
|
@@ -18,6 +18,11 @@ func apiRoute(p string) (string, string) {
|
||||
p = strings.TrimPrefix(p, "/")
|
||||
parts := strings.Split(p, "/")
|
||||
|
||||
// if we have 1 part assume name Name.Call
|
||||
if len(parts) == 1 && len(parts[0]) > 0 {
|
||||
return parts[0], methodName(append(parts, "Call"))
|
||||
}
|
||||
|
||||
// If we've got two or less parts
|
||||
// Use first part as service
|
||||
// Use all parts as method
|
||||
|
@@ -4,7 +4,6 @@ package registry
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/router"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/registry/cache"
|
||||
)
|
||||
@@ -68,7 +68,9 @@ func (r *registryRouter) refresh() {
|
||||
services, err := r.opts.Registry.ListServices()
|
||||
if err != nil {
|
||||
attempts++
|
||||
log.Println("Error listing endpoints", err)
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Errorf("unable to list services: %v", err)
|
||||
}
|
||||
time.Sleep(time.Duration(attempts) * time.Second)
|
||||
continue
|
||||
}
|
||||
@@ -83,6 +85,9 @@ func (r *registryRouter) refresh() {
|
||||
}
|
||||
service, err := r.rc.GetService(s.Name)
|
||||
if err != nil {
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Errorf("unable to get service: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
r.store(service)
|
||||
@@ -107,6 +112,9 @@ func (r *registryRouter) process(res *registry.Result) {
|
||||
// get entry from cache
|
||||
service, err := r.rc.GetService(res.Service.Name)
|
||||
if err != nil {
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Errorf("unable to get service: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -136,6 +144,9 @@ func (r *registryRouter) store(services []*registry.Service) {
|
||||
|
||||
// if we got nothing skip
|
||||
if err := api.Validate(end); err != nil {
|
||||
if logger.V(logger.TraceLevel, logger.DefaultLogger) {
|
||||
logger.Tracef("endpoint validation failed: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -188,7 +199,9 @@ func (r *registryRouter) watch() {
|
||||
w, err := r.opts.Registry.Watch()
|
||||
if err != nil {
|
||||
attempts++
|
||||
log.Println("Error watching endpoints", err)
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Errorf("error watching endpoints: %v", err)
|
||||
}
|
||||
time.Sleep(time.Duration(attempts) * time.Second)
|
||||
continue
|
||||
}
|
||||
@@ -211,7 +224,9 @@ func (r *registryRouter) watch() {
|
||||
// process next event
|
||||
res, err := w.Next()
|
||||
if err != nil {
|
||||
log.Println("Error getting next endpoint", err)
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Errorf("error getting next endoint: %v", err)
|
||||
}
|
||||
close(ch)
|
||||
break
|
||||
}
|
||||
@@ -235,6 +250,14 @@ func (r *registryRouter) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *registryRouter) Register(ep *api.Endpoint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *registryRouter) Deregister(ep *api.Endpoint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *registryRouter) Endpoint(req *http.Request) (*api.Service, error) {
|
||||
if r.isClosed() {
|
||||
return nil, errors.New("router closed")
|
||||
|
@@ -15,6 +15,10 @@ type Router interface {
|
||||
Close() error
|
||||
// Endpoint returns an api.Service endpoint or an error if it does not exist
|
||||
Endpoint(r *http.Request) (*api.Service, error)
|
||||
// Register endpoint in router
|
||||
Register(ep *api.Endpoint) error
|
||||
// Deregister endpoint from router
|
||||
Deregister(ep *api.Endpoint) error
|
||||
// Route returns an api.Service route
|
||||
Route(r *http.Request) (*api.Service, error)
|
||||
}
|
||||
|
304
api/router/static/static.go
Normal file
304
api/router/static/static.go
Normal file
@@ -0,0 +1,304 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/router"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
type endpoint struct {
|
||||
apiep *api.Endpoint
|
||||
hostregs []*regexp.Regexp
|
||||
pathregs []runtime.Pattern
|
||||
}
|
||||
|
||||
// router is the default router
|
||||
type staticRouter struct {
|
||||
exit chan bool
|
||||
opts router.Options
|
||||
sync.RWMutex
|
||||
eps map[string]*endpoint
|
||||
}
|
||||
|
||||
func (r *staticRouter) isClosed() bool {
|
||||
select {
|
||||
case <-r.exit:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// watch for endpoint changes
|
||||
func (r *staticRouter) watch() {
|
||||
var attempts int
|
||||
|
||||
for {
|
||||
if r.isClosed() {
|
||||
return
|
||||
}
|
||||
|
||||
// watch for changes
|
||||
w, err := r.opts.Registry.Watch()
|
||||
if err != nil {
|
||||
attempts++
|
||||
log.Println("Error watching endpoints", err)
|
||||
time.Sleep(time.Duration(attempts) * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
ch := make(chan bool)
|
||||
|
||||
go func() {
|
||||
select {
|
||||
case <-ch:
|
||||
w.Stop()
|
||||
case <-r.exit:
|
||||
w.Stop()
|
||||
}
|
||||
}()
|
||||
|
||||
// reset if we get here
|
||||
attempts = 0
|
||||
|
||||
for {
|
||||
// process next event
|
||||
res, err := w.Next()
|
||||
if err != nil {
|
||||
log.Println("Error getting next endpoint", err)
|
||||
close(ch)
|
||||
break
|
||||
}
|
||||
r.process(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func (r *staticRouter) Register(ep *api.Endpoint) error {
|
||||
if err := api.Validate(ep); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var pathregs []runtime.Pattern
|
||||
var hostregs []*regexp.Regexp
|
||||
|
||||
for _, h := range ep.Host {
|
||||
if h == "" || h == "*" {
|
||||
continue
|
||||
}
|
||||
hostreg, err := regexp.CompilePOSIX(h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hostregs = append(hostregs, hostreg)
|
||||
}
|
||||
|
||||
for _, p := range ep.Path {
|
||||
rule, err := httprule.Parse(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tpl := rule.Compile()
|
||||
pathreg, err := runtime.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pathregs = append(pathregs, pathreg)
|
||||
}
|
||||
|
||||
r.Lock()
|
||||
r.eps[ep.Name] = &endpoint{apiep: ep, pathregs: pathregs, hostregs: hostregs}
|
||||
r.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *staticRouter) Deregister(ep *api.Endpoint) error {
|
||||
if err := api.Validate(ep); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Lock()
|
||||
delete(r.eps, ep.Name)
|
||||
r.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *staticRouter) Options() router.Options {
|
||||
return r.opts
|
||||
}
|
||||
|
||||
func (r *staticRouter) Close() error {
|
||||
select {
|
||||
case <-r.exit:
|
||||
return nil
|
||||
default:
|
||||
close(r.exit)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *staticRouter) Endpoint(req *http.Request) (*api.Service, error) {
|
||||
ep, err := r.endpoint(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
epf := strings.Split(ep.apiep.Name, ".")
|
||||
services, err := r.opts.Registry.GetService(epf[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// hack for stream endpoint
|
||||
if ep.apiep.Stream {
|
||||
for _, svc := range services {
|
||||
for _, e := range svc.Endpoints {
|
||||
e.Name = strings.Join(epf[1:], ".")
|
||||
e.Metadata = make(map[string]string)
|
||||
e.Metadata["stream"] = "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
svc := &api.Service{
|
||||
Name: epf[0],
|
||||
Endpoint: &api.Endpoint{
|
||||
Name: strings.Join(epf[1:], "."),
|
||||
Handler: "rpc",
|
||||
Host: ep.apiep.Host,
|
||||
Method: ep.apiep.Method,
|
||||
Path: ep.apiep.Path,
|
||||
},
|
||||
Services: services,
|
||||
}
|
||||
|
||||
return svc, nil
|
||||
}
|
||||
|
||||
func (r *staticRouter) endpoint(req *http.Request) (*endpoint, error) {
|
||||
if r.isClosed() {
|
||||
return nil, errors.New("router closed")
|
||||
}
|
||||
|
||||
r.RLock()
|
||||
defer r.RUnlock()
|
||||
|
||||
var idx int
|
||||
if len(req.URL.Path) > 0 && req.URL.Path != "/" {
|
||||
idx = 1
|
||||
}
|
||||
path := strings.Split(req.URL.Path[idx:], "/")
|
||||
// use the first match
|
||||
// TODO: weighted matching
|
||||
|
||||
for _, ep := range r.eps {
|
||||
var mMatch, hMatch, pMatch bool
|
||||
|
||||
// 1. try method
|
||||
methodLoop:
|
||||
for _, m := range ep.apiep.Method {
|
||||
if m == req.Method {
|
||||
mMatch = true
|
||||
break methodLoop
|
||||
}
|
||||
}
|
||||
if !mMatch {
|
||||
continue
|
||||
}
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("api method match %s", req.Method)
|
||||
}
|
||||
|
||||
// 2. try host
|
||||
if len(ep.apiep.Host) == 0 {
|
||||
hMatch = true
|
||||
} else {
|
||||
hostLoop:
|
||||
for idx, h := range ep.apiep.Host {
|
||||
if h == "" || h == "*" {
|
||||
hMatch = true
|
||||
break hostLoop
|
||||
} else {
|
||||
if ep.hostregs[idx].MatchString(req.URL.Host) {
|
||||
hMatch = true
|
||||
break hostLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hMatch {
|
||||
continue
|
||||
}
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("api host match %s", req.URL.Host)
|
||||
}
|
||||
|
||||
// 3. try path
|
||||
pathLoop:
|
||||
for _, pathreg := range ep.pathregs {
|
||||
matches, err := pathreg.Match(path, "")
|
||||
if err != nil {
|
||||
// TODO: log error
|
||||
continue
|
||||
}
|
||||
pMatch = true
|
||||
ctx := req.Context()
|
||||
md, ok := metadata.FromContext(ctx)
|
||||
if !ok {
|
||||
md = make(metadata.Metadata)
|
||||
}
|
||||
for k, v := range matches {
|
||||
md[fmt.Sprintf("x-api-field-%s", k)] = v
|
||||
}
|
||||
*req = *req.WithContext(context.WithValue(ctx, metadata.MetadataKey{}, md))
|
||||
break pathLoop
|
||||
}
|
||||
if !pMatch {
|
||||
continue
|
||||
}
|
||||
// TODO: Percentage traffic
|
||||
|
||||
// we got here, so its a match
|
||||
return ep, nil
|
||||
}
|
||||
// no match
|
||||
return nil, fmt.Errorf("endpoint not found for %v", req)
|
||||
}
|
||||
|
||||
func (r *staticRouter) Route(req *http.Request) (*api.Service, error) {
|
||||
if r.isClosed() {
|
||||
return nil, errors.New("router closed")
|
||||
}
|
||||
|
||||
// try get an endpoint
|
||||
ep, err := r.Endpoint(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ep, nil
|
||||
}
|
||||
|
||||
func NewRouter(opts ...router.Option) *staticRouter {
|
||||
options := router.NewOptions(opts...)
|
||||
r := &staticRouter{
|
||||
exit: make(chan bool),
|
||||
opts: options,
|
||||
eps: make(map[string]*endpoint),
|
||||
}
|
||||
//go r.watch()
|
||||
//go r.refresh()
|
||||
return r
|
||||
}
|
@@ -4,11 +4,11 @@ package autocert
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/micro/go-micro/v2/api/server/acme"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
)
|
||||
|
||||
@@ -31,7 +31,9 @@ func (a *autocertProvider) TLSConfig(hosts ...string) (*tls.Config, error) {
|
||||
}
|
||||
dir := cacheDir()
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
log.Printf("warning: autocert not using a cache: %v", err)
|
||||
if logger.V(logger.InfoLevel, logger.DefaultLogger) {
|
||||
logger.Infof("warning: autocert not using a cache: %v", err)
|
||||
}
|
||||
} else {
|
||||
m.Cache = autocert.DirCache(dir)
|
||||
}
|
||||
|
@@ -3,14 +3,13 @@ package certmagic
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/mholt/certmagic"
|
||||
|
||||
"github.com/micro/go-micro/v2/api/server/acme"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type certmagicProvider struct {
|
||||
@@ -48,7 +47,7 @@ func (c *certmagicProvider) TLSConfig(hosts ...string) (*tls.Config, error) {
|
||||
return certmagic.TLS(hosts)
|
||||
}
|
||||
|
||||
// New returns a certmagic provider
|
||||
// NewProvider returns a certmagic provider
|
||||
func NewProvider(options ...acme.Option) acme.Provider {
|
||||
opts := acme.DefaultOptions()
|
||||
|
||||
@@ -58,7 +57,7 @@ func NewProvider(options ...acme.Option) acme.Provider {
|
||||
|
||||
if opts.Cache != nil {
|
||||
if _, ok := opts.Cache.(certmagic.Storage); !ok {
|
||||
log.Fatal("ACME: cache provided doesn't implement certmagic's Storage interface")
|
||||
logger.Fatal("ACME: cache provided doesn't implement certmagic's Storage interface")
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -88,16 +88,16 @@ func (s *storage) Exists(key string) bool {
|
||||
}
|
||||
|
||||
func (s *storage) List(prefix string, recursive bool) ([]string, error) {
|
||||
records, err := s.store.List()
|
||||
keys, err := s.store.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//nolint:prealloc
|
||||
var results []string
|
||||
for _, r := range records {
|
||||
if strings.HasPrefix(r.Key, prefix) {
|
||||
results = append(results, r.Key)
|
||||
for _, k := range keys {
|
||||
if strings.HasPrefix(k, prefix) {
|
||||
results = append(results, k)
|
||||
}
|
||||
}
|
||||
if recursive {
|
||||
|
79
api/server/auth/auth.go
Normal file
79
api/server/auth/auth.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
)
|
||||
|
||||
// CombinedAuthHandler wraps a server and authenticates requests
|
||||
func CombinedAuthHandler(h http.Handler) http.Handler {
|
||||
return authHandler{
|
||||
handler: h,
|
||||
auth: auth.DefaultAuth,
|
||||
}
|
||||
}
|
||||
|
||||
type authHandler struct {
|
||||
handler http.Handler
|
||||
auth auth.Auth
|
||||
}
|
||||
|
||||
func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
// Extract the token from the request
|
||||
var token string
|
||||
if header := req.Header.Get("Authorization"); len(header) > 0 {
|
||||
// Extract the auth token from the request
|
||||
if strings.HasPrefix(header, auth.BearerScheme) {
|
||||
token = header[len(auth.BearerScheme):]
|
||||
}
|
||||
} else {
|
||||
// Get the token out the cookies if not provided in headers
|
||||
if c, err := req.Cookie("micro-token"); err == nil && c != nil {
|
||||
token = strings.TrimPrefix(c.Value, auth.TokenCookieName+"=")
|
||||
req.Header.Set("Authorization", auth.BearerScheme+token)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the account using the token, fallback to a blank account
|
||||
// since some endpoints can be unauthenticated, so the lack of an
|
||||
// account doesn't necesserially mean a forbidden request
|
||||
acc, err := h.auth.Inspect(token)
|
||||
if err != nil {
|
||||
acc = &auth.Account{}
|
||||
}
|
||||
err = h.auth.Verify(acc, &auth.Resource{
|
||||
Type: "service",
|
||||
Name: "go.micro.web",
|
||||
Endpoint: req.URL.Path,
|
||||
})
|
||||
|
||||
// The account has the necessary permissions to access the
|
||||
// resource
|
||||
if err == nil {
|
||||
h.handler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
// The account is set, but they don't have enough permissions,
|
||||
// hence we 403.
|
||||
if len(acc.ID) > 0 {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// If there is no auth login url set, 401
|
||||
loginURL := h.auth.Options().LoginURL
|
||||
if loginURL == "" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect to the login path
|
||||
params := url.Values{"redirect_to": {req.URL.Path}}
|
||||
loginWithRedirect := fmt.Sprintf("%v?%v", loginURL, params.Encode())
|
||||
http.Redirect(w, req, loginWithRedirect, http.StatusTemporaryRedirect)
|
||||
}
|
44
api/server/cors/cors.go
Normal file
44
api/server/cors/cors.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package cors
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CombinedCORSHandler wraps a server and provides CORS headers
|
||||
func CombinedCORSHandler(h http.Handler) http.Handler {
|
||||
return corsHandler{h}
|
||||
}
|
||||
|
||||
type corsHandler struct {
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
func (c corsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
SetHeaders(w, r)
|
||||
|
||||
if r.Method == "OPTIONS" {
|
||||
return
|
||||
}
|
||||
|
||||
c.handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// SetHeaders sets the CORS headers
|
||||
func SetHeaders(w http.ResponseWriter, r *http.Request) {
|
||||
set := func(w http.ResponseWriter, k, v string) {
|
||||
if v := w.Header().Get(k); len(v) > 0 {
|
||||
return
|
||||
}
|
||||
w.Header().Set(k, v)
|
||||
}
|
||||
|
||||
if origin := r.Header.Get("Origin"); len(origin) > 0 {
|
||||
set(w, "Access-Control-Allow-Origin", origin)
|
||||
} else {
|
||||
set(w, "Access-Control-Allow-Origin", "*")
|
||||
}
|
||||
|
||||
set(w, "Access-Control-Allow-Credentials", "true")
|
||||
set(w, "Access-Control-Allow-Methods", "POST, PATCH, GET, OPTIONS, PUT, DELETE")
|
||||
set(w, "Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
|
||||
}
|
@@ -8,9 +8,12 @@ import (
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/micro/go-micro/v2/api/server/auth"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/micro/go-micro/v2/api/server"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/api/server/cors"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type httpServer struct {
|
||||
@@ -45,7 +48,14 @@ func (s *httpServer) Init(opts ...server.Option) error {
|
||||
}
|
||||
|
||||
func (s *httpServer) Handle(path string, handler http.Handler) {
|
||||
s.mux.Handle(path, handlers.CombinedLoggingHandler(os.Stdout, handler))
|
||||
h := handlers.CombinedLoggingHandler(os.Stdout, handler)
|
||||
h = auth.CombinedAuthHandler(handler)
|
||||
|
||||
if s.opts.EnableCORS {
|
||||
h = cors.CombinedCORSHandler(h)
|
||||
}
|
||||
|
||||
s.mux.Handle(path, h)
|
||||
}
|
||||
|
||||
func (s *httpServer) Start() error {
|
||||
@@ -65,7 +75,9 @@ func (s *httpServer) Start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("HTTP API Listening on %s", l.Addr().String())
|
||||
if logger.V(logger.InfoLevel, logger.DefaultLogger) {
|
||||
logger.Infof("HTTP API Listening on %s", l.Addr().String())
|
||||
}
|
||||
|
||||
s.mtx.Lock()
|
||||
s.address = l.Addr().String()
|
||||
@@ -74,7 +86,7 @@ func (s *httpServer) Start() error {
|
||||
go func() {
|
||||
if err := http.Serve(l, s.mux); err != nil {
|
||||
// temporary fix
|
||||
//log.Fatal(err)
|
||||
//logger.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@@ -10,12 +10,19 @@ type Option func(o *Options)
|
||||
|
||||
type Options struct {
|
||||
EnableACME bool
|
||||
EnableCORS bool
|
||||
ACMEProvider acme.Provider
|
||||
EnableTLS bool
|
||||
ACMEHosts []string
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
func EnableCORS(b bool) Option {
|
||||
return func(o *Options) {
|
||||
o.EnableCORS = b
|
||||
}
|
||||
}
|
||||
|
||||
func EnableACME(b bool) Option {
|
||||
return func(o *Options) {
|
||||
o.EnableACME = b
|
||||
|
268
api/service/proto/api.pb.go
Normal file
268
api/service/proto/api.pb.go
Normal file
@@ -0,0 +1,268 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: api/service/proto/api.proto
|
||||
|
||||
package go_micro_api
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Endpoint struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Host []string `protobuf:"bytes,2,rep,name=host,proto3" json:"host,omitempty"`
|
||||
Path []string `protobuf:"bytes,3,rep,name=path,proto3" json:"path,omitempty"`
|
||||
Method []string `protobuf:"bytes,4,rep,name=method,proto3" json:"method,omitempty"`
|
||||
Stream bool `protobuf:"varint,5,opt,name=stream,proto3" json:"stream,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Endpoint) Reset() { *m = Endpoint{} }
|
||||
func (m *Endpoint) String() string { return proto.CompactTextString(m) }
|
||||
func (*Endpoint) ProtoMessage() {}
|
||||
func (*Endpoint) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_c4a48b6b680b5c31, []int{0}
|
||||
}
|
||||
|
||||
func (m *Endpoint) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Endpoint.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Endpoint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Endpoint.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Endpoint) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Endpoint.Merge(m, src)
|
||||
}
|
||||
func (m *Endpoint) XXX_Size() int {
|
||||
return xxx_messageInfo_Endpoint.Size(m)
|
||||
}
|
||||
func (m *Endpoint) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Endpoint.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Endpoint proto.InternalMessageInfo
|
||||
|
||||
func (m *Endpoint) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Endpoint) GetHost() []string {
|
||||
if m != nil {
|
||||
return m.Host
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Endpoint) GetPath() []string {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Endpoint) GetMethod() []string {
|
||||
if m != nil {
|
||||
return m.Method
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Endpoint) GetStream() bool {
|
||||
if m != nil {
|
||||
return m.Stream
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type EmptyResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *EmptyResponse) Reset() { *m = EmptyResponse{} }
|
||||
func (m *EmptyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyResponse) ProtoMessage() {}
|
||||
func (*EmptyResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_c4a48b6b680b5c31, []int{1}
|
||||
}
|
||||
|
||||
func (m *EmptyResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EmptyResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_EmptyResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_EmptyResponse.Merge(m, src)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_EmptyResponse.Size(m)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_EmptyResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_EmptyResponse proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Endpoint)(nil), "go.micro.api.Endpoint")
|
||||
proto.RegisterType((*EmptyResponse)(nil), "go.micro.api.EmptyResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("api/service/proto/api.proto", fileDescriptor_c4a48b6b680b5c31) }
|
||||
|
||||
var fileDescriptor_c4a48b6b680b5c31 = []byte{
|
||||
// 212 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0xd0, 0xc1, 0x4a, 0x03, 0x31,
|
||||
0x10, 0x80, 0x61, 0xd7, 0xad, 0x65, 0x1d, 0x14, 0x21, 0x87, 0x12, 0xec, 0x65, 0xd9, 0x53, 0x4f,
|
||||
0x59, 0xd0, 0x27, 0x28, 0xda, 0x17, 0xd8, 0x37, 0x88, 0xed, 0xd0, 0x9d, 0x43, 0x32, 0x43, 0x32,
|
||||
0x14, 0x7c, 0x08, 0xdf, 0x59, 0x12, 0x2b, 0x2c, 0x5e, 0xbd, 0xfd, 0xf3, 0x1d, 0x86, 0x61, 0x60,
|
||||
0xeb, 0x85, 0xc6, 0x8c, 0xe9, 0x42, 0x47, 0x1c, 0x25, 0xb1, 0xf2, 0xe8, 0x85, 0x5c, 0x2d, 0xf3,
|
||||
0x70, 0x66, 0x17, 0xe8, 0x98, 0xd8, 0x79, 0xa1, 0xe1, 0x02, 0xdd, 0x21, 0x9e, 0x84, 0x29, 0xaa,
|
||||
0x31, 0xb0, 0x8a, 0x3e, 0xa0, 0x6d, 0xfa, 0x66, 0x77, 0x3f, 0xd5, 0x2e, 0x36, 0x73, 0x56, 0x7b,
|
||||
0xdb, 0xb7, 0xc5, 0x4a, 0x17, 0x13, 0xaf, 0xb3, 0x6d, 0x7f, 0xac, 0xb4, 0xd9, 0xc0, 0x3a, 0xa0,
|
||||
0xce, 0x7c, 0xb2, 0xab, 0xaa, 0xd7, 0xa9, 0x78, 0xd6, 0x84, 0x3e, 0xd8, 0xbb, 0xbe, 0xd9, 0x75,
|
||||
0xd3, 0x75, 0x1a, 0x9e, 0xe0, 0xf1, 0x10, 0x44, 0x3f, 0x27, 0xcc, 0xc2, 0x31, 0xe3, 0xcb, 0x57,
|
||||
0x03, 0xed, 0x5e, 0xc8, 0xec, 0xa1, 0x9b, 0xf0, 0x4c, 0x59, 0x31, 0x99, 0x8d, 0x5b, 0xde, 0xea,
|
||||
0x7e, 0x0f, 0x7d, 0xde, 0xfe, 0xf1, 0xe5, 0xa2, 0xe1, 0xc6, 0xbc, 0x01, 0xbc, 0x63, 0xfa, 0xdf,
|
||||
0x92, 0x8f, 0x75, 0xfd, 0xd6, 0xeb, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x46, 0x62, 0x67, 0x30,
|
||||
0x4c, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// ApiClient is the client API for Api service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type ApiClient interface {
|
||||
Register(ctx context.Context, in *Endpoint, opts ...grpc.CallOption) (*EmptyResponse, error)
|
||||
Deregister(ctx context.Context, in *Endpoint, opts ...grpc.CallOption) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
type apiClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewApiClient(cc *grpc.ClientConn) ApiClient {
|
||||
return &apiClient{cc}
|
||||
}
|
||||
|
||||
func (c *apiClient) Register(ctx context.Context, in *Endpoint, opts ...grpc.CallOption) (*EmptyResponse, error) {
|
||||
out := new(EmptyResponse)
|
||||
err := c.cc.Invoke(ctx, "/go.micro.api.Api/Register", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *apiClient) Deregister(ctx context.Context, in *Endpoint, opts ...grpc.CallOption) (*EmptyResponse, error) {
|
||||
out := new(EmptyResponse)
|
||||
err := c.cc.Invoke(ctx, "/go.micro.api.Api/Deregister", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ApiServer is the server API for Api service.
|
||||
type ApiServer interface {
|
||||
Register(context.Context, *Endpoint) (*EmptyResponse, error)
|
||||
Deregister(context.Context, *Endpoint) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedApiServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedApiServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedApiServer) Register(ctx context.Context, req *Endpoint) (*EmptyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Register not implemented")
|
||||
}
|
||||
func (*UnimplementedApiServer) Deregister(ctx context.Context, req *Endpoint) (*EmptyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Deregister not implemented")
|
||||
}
|
||||
|
||||
func RegisterApiServer(s *grpc.Server, srv ApiServer) {
|
||||
s.RegisterService(&_Api_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Api_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Endpoint)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ApiServer).Register(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/go.micro.api.Api/Register",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ApiServer).Register(ctx, req.(*Endpoint))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Api_Deregister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Endpoint)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ApiServer).Deregister(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/go.micro.api.Api/Deregister",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ApiServer).Deregister(ctx, req.(*Endpoint))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Api_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "go.micro.api.Api",
|
||||
HandlerType: (*ApiServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Register",
|
||||
Handler: _Api_Register_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Deregister",
|
||||
Handler: _Api_Deregister_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/service/proto/api.proto",
|
||||
}
|
102
api/service/proto/api.pb.micro.go
Normal file
102
api/service/proto/api.pb.micro.go
Normal file
@@ -0,0 +1,102 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: api/service/proto/api.proto
|
||||
|
||||
package go_micro_api
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Api service
|
||||
|
||||
type ApiService interface {
|
||||
Register(ctx context.Context, in *Endpoint, opts ...client.CallOption) (*EmptyResponse, error)
|
||||
Deregister(ctx context.Context, in *Endpoint, opts ...client.CallOption) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
type apiService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewApiService(name string, c client.Client) ApiService {
|
||||
return &apiService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *apiService) Register(ctx context.Context, in *Endpoint, opts ...client.CallOption) (*EmptyResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Api.Register", in)
|
||||
out := new(EmptyResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *apiService) Deregister(ctx context.Context, in *Endpoint, opts ...client.CallOption) (*EmptyResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Api.Deregister", in)
|
||||
out := new(EmptyResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Api service
|
||||
|
||||
type ApiHandler interface {
|
||||
Register(context.Context, *Endpoint, *EmptyResponse) error
|
||||
Deregister(context.Context, *Endpoint, *EmptyResponse) error
|
||||
}
|
||||
|
||||
func RegisterApiHandler(s server.Server, hdlr ApiHandler, opts ...server.HandlerOption) error {
|
||||
type api interface {
|
||||
Register(ctx context.Context, in *Endpoint, out *EmptyResponse) error
|
||||
Deregister(ctx context.Context, in *Endpoint, out *EmptyResponse) error
|
||||
}
|
||||
type Api struct {
|
||||
api
|
||||
}
|
||||
h := &apiHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Api{h}, opts...))
|
||||
}
|
||||
|
||||
type apiHandler struct {
|
||||
ApiHandler
|
||||
}
|
||||
|
||||
func (h *apiHandler) Register(ctx context.Context, in *Endpoint, out *EmptyResponse) error {
|
||||
return h.ApiHandler.Register(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *apiHandler) Deregister(ctx context.Context, in *Endpoint, out *EmptyResponse) error {
|
||||
return h.ApiHandler.Deregister(ctx, in, out)
|
||||
}
|
18
api/service/proto/api.proto
Normal file
18
api/service/proto/api.proto
Normal file
@@ -0,0 +1,18 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package go.micro.api;
|
||||
|
||||
service Api {
|
||||
rpc Register(Endpoint) returns (EmptyResponse) {};
|
||||
rpc Deregister(Endpoint) returns (EmptyResponse) {};
|
||||
}
|
||||
|
||||
message Endpoint {
|
||||
string name = 1;
|
||||
repeated string host = 2;
|
||||
repeated string path = 3;
|
||||
repeated string method = 4;
|
||||
bool stream = 5;
|
||||
}
|
||||
|
||||
message EmptyResponse {}
|
135
auth/auth.go
135
auth/auth.go
@@ -2,22 +2,49 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotFound is returned when a resouce cannot be found
|
||||
ErrNotFound = errors.New("not found")
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
ErrEncodingToken = errors.New("error encoding the token")
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
ErrInvalidToken = errors.New("invalid token provided")
|
||||
// ErrInvalidRole is returned when the role provided was invalid
|
||||
ErrInvalidRole = errors.New("invalid role")
|
||||
// ErrForbidden is returned when a user does not have the necessary roles to access a resource
|
||||
ErrForbidden = errors.New("resource forbidden")
|
||||
// BearerScheme used for Authorization header
|
||||
BearerScheme = "Bearer "
|
||||
)
|
||||
|
||||
// Auth providers authentication and authorization
|
||||
type Auth interface {
|
||||
// Init the auth package
|
||||
Init(opts ...Option) error
|
||||
// Options returns the options set
|
||||
// Init the auth
|
||||
Init(opts ...Option)
|
||||
// Options set for auth
|
||||
Options() Options
|
||||
// Generate a new auth Account
|
||||
// Generate a new account
|
||||
Generate(id string, opts ...GenerateOption) (*Account, error)
|
||||
// Revoke an authorization Account
|
||||
Revoke(token string) error
|
||||
// Validate an account token
|
||||
Validate(token string) (*Account, error)
|
||||
// String returns the implementation
|
||||
// Grant access to a resource
|
||||
Grant(role string, res *Resource) error
|
||||
// Revoke access to a resource
|
||||
Revoke(role string, res *Resource) error
|
||||
// Verify an account has access to a resource
|
||||
Verify(acc *Account, res *Resource) error
|
||||
// Inspect a token
|
||||
Inspect(token string) (*Account, error)
|
||||
// Token generated using an account ID and secret
|
||||
Token(id, secret string, opts ...TokenOption) (*Token, error)
|
||||
// String returns the name of the implementation
|
||||
String() string
|
||||
}
|
||||
|
||||
@@ -27,26 +54,86 @@ type Resource struct {
|
||||
Name string
|
||||
// Type of resource, e.g.
|
||||
Type string
|
||||
}
|
||||
|
||||
// Role an account has
|
||||
type Role struct {
|
||||
Name string
|
||||
Resource *Resource
|
||||
// Endpoint resource e.g NotesService.Create
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
// Account provided by an auth provider
|
||||
type Account struct {
|
||||
// ID of the account (UUID or email)
|
||||
Id string `json:"id"`
|
||||
// Token used to authenticate
|
||||
Token string `json:"token"`
|
||||
// Time of Account creation
|
||||
Created time.Time `json:"created"`
|
||||
// Time of Account expiry
|
||||
Expiry time.Time `json:"expiry"`
|
||||
// ID of the account (UUIDV4, email or username)
|
||||
ID string `json:"id"`
|
||||
// Secret used to renew the account
|
||||
Secret string `json:"secret"`
|
||||
// Roles associated with the Account
|
||||
Roles []*Role `json:"roles"`
|
||||
Roles []string `json:"roles"`
|
||||
// Any other associated metadata
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
// Namespace the account belongs to, default blank
|
||||
Namespace string `json:"namespace"`
|
||||
}
|
||||
|
||||
// Token can be short or long lived
|
||||
type Token struct {
|
||||
// The token itself
|
||||
Token string `json:"token"`
|
||||
// Type of token, e.g. JWT
|
||||
Type string `json:"type"`
|
||||
// Time of token creation
|
||||
Created time.Time `json:"created"`
|
||||
// Time of token expiry
|
||||
Expiry time.Time `json:"expiry"`
|
||||
// Subject of the token, e.g. the account ID
|
||||
Subject string `json:"subject"`
|
||||
// Roles granted to the token
|
||||
Roles []string `json:"roles"`
|
||||
// Metadata embedded in the token
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
// Namespace the token belongs to
|
||||
Namespace string `json:"namespace"`
|
||||
}
|
||||
|
||||
const (
|
||||
// MetadataKey is the key used when storing the account in metadata
|
||||
MetadataKey = "auth-account"
|
||||
// TokenCookieName is the name of the cookie which stores the auth token
|
||||
TokenCookieName = "micro-token"
|
||||
// SecretCookieName is the name of the cookie which stores the auth secret
|
||||
SecretCookieName = "micro-secret"
|
||||
)
|
||||
|
||||
// AccountFromContext gets the account from the context, which
|
||||
// is set by the auth wrapper at the start of a call. If the account
|
||||
// is not set, a nil account will be returned. The error is only returned
|
||||
// when there was a problem retrieving an account
|
||||
func AccountFromContext(ctx context.Context) (*Account, error) {
|
||||
str, ok := metadata.Get(ctx, MetadataKey)
|
||||
// there was no account set
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var acc *Account
|
||||
// metadata is stored as a string, so unmarshal to an account
|
||||
if err := json.Unmarshal([]byte(str), &acc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// ContextWithAccount sets the account in the context
|
||||
func ContextWithAccount(ctx context.Context, account *Account) (context.Context, error) {
|
||||
// metadata is stored as a string, so marshal to bytes
|
||||
bytes, err := json.Marshal(account)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// generate a new context with the MetadataKey set
|
||||
return metadata.Set(ctx, MetadataKey, string(bytes)), nil
|
||||
}
|
||||
|
||||
// ContextWithToken sets the auth token in the context
|
||||
func ContextWithToken(ctx context.Context, token string) context.Context {
|
||||
return metadata.Set(ctx, "Authorization", fmt.Sprintf("%v%v", BearerScheme, token))
|
||||
}
|
||||
|
@@ -1,36 +1,73 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultAuth = NewAuth()
|
||||
)
|
||||
|
||||
// NewAuth returns a new default registry which is noop
|
||||
func NewAuth(opts ...Option) Auth {
|
||||
return noop{}
|
||||
return &noop{}
|
||||
}
|
||||
|
||||
type noop struct{}
|
||||
|
||||
func (noop) Init(opts ...Option) error {
|
||||
return nil
|
||||
type noop struct {
|
||||
opts Options
|
||||
}
|
||||
|
||||
func (noop) Options() Options {
|
||||
return Options{}
|
||||
}
|
||||
|
||||
func (noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (noop) Revoke(token string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noop) Validate(token string) (*Account, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (noop) String() string {
|
||||
// String returns the name of the implementation
|
||||
func (n *noop) String() string {
|
||||
return "noop"
|
||||
}
|
||||
|
||||
// Init the auth
|
||||
func (n *noop) Init(opts ...Option) {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
}
|
||||
|
||||
// Options set for auth
|
||||
func (n *noop) Options() Options {
|
||||
return n.opts
|
||||
}
|
||||
|
||||
// Generate a new account
|
||||
func (n *noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
|
||||
options := NewGenerateOptions(opts...)
|
||||
|
||||
return &Account{
|
||||
ID: id,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
Secret: uuid.New().String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Grant access to a resource
|
||||
func (n *noop) Grant(role string, res *Resource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Revoke access to a resource
|
||||
func (n *noop) Revoke(role string, res *Resource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (n *noop) Verify(acc *Account, res *Resource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (n *noop) Inspect(token string) (*Account, error) {
|
||||
return &Account{
|
||||
ID: uuid.New().String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Token generation using an account id and secret
|
||||
func (n *noop) Token(id, secret string, opts ...TokenOption) (*Token, error) {
|
||||
return &Token{}, nil
|
||||
}
|
||||
|
120
auth/jwt/jwt.go
120
auth/jwt/jwt.go
@@ -1,120 +0,0 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
)
|
||||
|
||||
// ErrInvalidPrivateKey is returned when the service provided an invalid private key
|
||||
var ErrInvalidPrivateKey = errors.New("An invalid private key was provided")
|
||||
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
var ErrEncodingToken = errors.New("An error occured while encoding the JWT")
|
||||
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
var ErrInvalidToken = errors.New("An invalid token was provided")
|
||||
|
||||
// ErrMissingToken is returned when no token is provided
|
||||
var ErrMissingToken = errors.New("A valid JWT is required")
|
||||
|
||||
// NewAuth returns a new instance of the Auth service
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
svc := new(svc)
|
||||
svc.Init(opts...)
|
||||
return svc
|
||||
}
|
||||
|
||||
// svc is the JWT implementation of the Auth interface
|
||||
type svc struct {
|
||||
options auth.Options
|
||||
}
|
||||
|
||||
func (s *svc) String() string {
|
||||
return "jwt"
|
||||
}
|
||||
|
||||
func (s *svc) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
func (s *svc) Init(opts ...auth.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthClaims to be encoded in the JWT
|
||||
type AuthClaims struct {
|
||||
Id string `json:"id"`
|
||||
Roles []*auth.Role `json:"roles"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// Generate a new JWT
|
||||
func (s *svc) Generate(id string, ops ...auth.GenerateOption) (*auth.Account, error) {
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM(s.options.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, ErrEncodingToken
|
||||
}
|
||||
|
||||
options := auth.NewGenerateOptions(ops...)
|
||||
account := jwt.NewWithClaims(jwt.SigningMethodRS256, AuthClaims{
|
||||
id, options.Roles, options.Metadata, jwt.StandardClaims{
|
||||
Subject: id,
|
||||
ExpiresAt: time.Now().Add(time.Hour * 24).Unix(),
|
||||
},
|
||||
})
|
||||
|
||||
token, err := account.SignedString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &auth.Account{
|
||||
Id: id,
|
||||
Token: token,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Revoke an authorization account
|
||||
func (s *svc) Revoke(token string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate a JWT
|
||||
func (s *svc) Validate(token string) (*auth.Account, error) {
|
||||
if token == "" {
|
||||
return nil, ErrMissingToken
|
||||
}
|
||||
|
||||
res, err := jwt.ParseWithClaims(token, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwt.ParseRSAPublicKeyFromPEM(s.options.PublicKey)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !res.Valid {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
claims, ok := res.Claims.(*AuthClaims)
|
||||
if !ok {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
return &auth.Account{
|
||||
Id: claims.Id,
|
||||
Metadata: claims.Metadata,
|
||||
Roles: claims.Roles,
|
||||
}, nil
|
||||
}
|
100
auth/options.go
100
auth/options.go
@@ -1,65 +1,137 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
b64 "encoding/base64"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth/provider"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
PublicKey []byte
|
||||
PrivateKey []byte
|
||||
Excludes []string
|
||||
// Token is an auth token
|
||||
Token string
|
||||
// Public key base64 encoded
|
||||
PublicKey string
|
||||
// Private key base64 encoded
|
||||
PrivateKey string
|
||||
// Provider is an auth provider
|
||||
Provider provider.Provider
|
||||
// LoginURL is the relative url path where a user can login
|
||||
LoginURL string
|
||||
// Store to back auth
|
||||
Store store.Store
|
||||
}
|
||||
|
||||
type Option func(o *Options)
|
||||
|
||||
// Excludes endpoints from auth
|
||||
func Excludes(excludes ...string) Option {
|
||||
// Store to back auth
|
||||
func Store(s store.Store) Option {
|
||||
return func(o *Options) {
|
||||
o.Excludes = excludes
|
||||
o.Store = s
|
||||
}
|
||||
}
|
||||
|
||||
// PublicKey is the JWT public key
|
||||
func PublicKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PublicKey, _ = b64.StdEncoding.DecodeString(key)
|
||||
o.PublicKey = key
|
||||
}
|
||||
}
|
||||
|
||||
// PrivateKey is the JWT private key
|
||||
func PrivateKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PrivateKey, _ = b64.StdEncoding.DecodeString(key)
|
||||
o.PrivateKey = key
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceToken sets an auth token
|
||||
func ServiceToken(t string) Option {
|
||||
return func(o *Options) {
|
||||
o.Token = t
|
||||
}
|
||||
}
|
||||
|
||||
// Provider set the auth provider
|
||||
func Provider(p provider.Provider) Option {
|
||||
return func(o *Options) {
|
||||
o.Provider = p
|
||||
}
|
||||
}
|
||||
|
||||
// LoginURL sets the auth LoginURL
|
||||
func LoginURL(url string) Option {
|
||||
return func(o *Options) {
|
||||
o.LoginURL = url
|
||||
}
|
||||
}
|
||||
|
||||
type GenerateOptions struct {
|
||||
// Metadata associated with the account
|
||||
Metadata map[string]string
|
||||
Roles []*Role
|
||||
// Roles/scopes associated with the account
|
||||
Roles []string
|
||||
// Namespace the account belongs too
|
||||
Namespace string
|
||||
}
|
||||
|
||||
type GenerateOption func(o *GenerateOptions)
|
||||
|
||||
// Metadata for the generated account
|
||||
func Metadata(md map[string]string) func(o *GenerateOptions) {
|
||||
// WithMetadata for the generated account
|
||||
func WithMetadata(md map[string]string) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Metadata = md
|
||||
}
|
||||
}
|
||||
|
||||
// Roles for the generated account
|
||||
func Roles(rs []*Role) func(o *GenerateOptions) {
|
||||
// WithRoles for the generated account
|
||||
func WithRoles(rs ...string) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Roles = rs
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace for the generated account
|
||||
func WithNamespace(n string) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Namespace = n
|
||||
}
|
||||
}
|
||||
|
||||
// NewGenerateOptions from a slice of options
|
||||
func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
|
||||
var options GenerateOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
type TokenOptions struct {
|
||||
// TokenExpiry is the time the token should live for
|
||||
TokenExpiry time.Duration
|
||||
}
|
||||
|
||||
type TokenOption func(o *TokenOptions)
|
||||
|
||||
// WithTokenExpiry for the token
|
||||
func WithTokenExpiry(ex time.Duration) TokenOption {
|
||||
return func(o *TokenOptions) {
|
||||
o.TokenExpiry = ex
|
||||
}
|
||||
}
|
||||
|
||||
// NewTokenOptions from a slice of options
|
||||
func NewTokenOptions(opts ...TokenOption) TokenOptions {
|
||||
var options TokenOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
// set defualt expiry of token
|
||||
if options.TokenExpiry == 0 {
|
||||
options.TokenExpiry = time.Minute
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
34
auth/provider/basic/basic.go
Normal file
34
auth/provider/basic/basic.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/v2/auth/provider"
|
||||
)
|
||||
|
||||
// NewProvider returns an initialised basic provider
|
||||
func NewProvider(opts ...provider.Option) provider.Provider {
|
||||
var options provider.Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &basic{options}
|
||||
}
|
||||
|
||||
type basic struct {
|
||||
opts provider.Options
|
||||
}
|
||||
|
||||
func (b *basic) String() string {
|
||||
return "basic"
|
||||
}
|
||||
|
||||
func (b *basic) Options() provider.Options {
|
||||
return b.opts
|
||||
}
|
||||
|
||||
func (b *basic) Endpoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *basic) Redirect() string {
|
||||
return ""
|
||||
}
|
54
auth/provider/oauth/oauth.go
Normal file
54
auth/provider/oauth/oauth.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth/provider"
|
||||
)
|
||||
|
||||
// NewProvider returns an initialised oauth provider
|
||||
func NewProvider(opts ...provider.Option) provider.Provider {
|
||||
var options provider.Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
return &oauth{options}
|
||||
}
|
||||
|
||||
type oauth struct {
|
||||
opts provider.Options
|
||||
}
|
||||
|
||||
func (o *oauth) String() string {
|
||||
return "oauth"
|
||||
}
|
||||
|
||||
func (o *oauth) Options() provider.Options {
|
||||
return o.opts
|
||||
}
|
||||
|
||||
func (o *oauth) Endpoint() string {
|
||||
params := make(url.Values)
|
||||
params.Add("response_type", "code")
|
||||
|
||||
if clientID := o.opts.ClientID; len(clientID) > 0 {
|
||||
params.Add("client_id", clientID)
|
||||
}
|
||||
|
||||
if scope := o.opts.Scope; len(scope) > 0 {
|
||||
// spaces are url encoded since this cannot be passed in env vars
|
||||
params.Add("scope", strings.ReplaceAll(scope, "%20", " "))
|
||||
}
|
||||
|
||||
if redir := o.Redirect(); len(redir) > 0 {
|
||||
params.Add("redirect_uri", redir)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v?%v", o.opts.Endpoint, params.Encode())
|
||||
}
|
||||
|
||||
func (o *oauth) Redirect() string {
|
||||
return o.opts.Redirect
|
||||
}
|
47
auth/provider/options.go
Normal file
47
auth/provider/options.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package provider
|
||||
|
||||
// Option returns a function which sets an option
|
||||
type Option func(*Options)
|
||||
|
||||
// Options a provider can have
|
||||
type Options struct {
|
||||
// ClientID is the application's ID.
|
||||
ClientID string
|
||||
// ClientSecret is the application's secret.
|
||||
ClientSecret string
|
||||
// Endpoint for the provider
|
||||
Endpoint string
|
||||
// Redirect url incase of UI
|
||||
Redirect string
|
||||
// Scope of the oauth request
|
||||
Scope string
|
||||
}
|
||||
|
||||
// Credentials is an option which sets the client id and secret
|
||||
func Credentials(id, secret string) Option {
|
||||
return func(o *Options) {
|
||||
o.ClientID = id
|
||||
o.ClientSecret = secret
|
||||
}
|
||||
}
|
||||
|
||||
// Endpoint sets the endpoint option
|
||||
func Endpoint(e string) Option {
|
||||
return func(o *Options) {
|
||||
o.Endpoint = e
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect sets the Redirect option
|
||||
func Redirect(r string) Option {
|
||||
return func(o *Options) {
|
||||
o.Redirect = r
|
||||
}
|
||||
}
|
||||
|
||||
// Scope sets the oauth scope
|
||||
func Scope(s string) Option {
|
||||
return func(o *Options) {
|
||||
o.Scope = s
|
||||
}
|
||||
}
|
28
auth/provider/provider.go
Normal file
28
auth/provider/provider.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Package provider is an external auth provider e.g oauth
|
||||
package provider
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Provider is an auth provider
|
||||
type Provider interface {
|
||||
// String returns the name of the provider
|
||||
String() string
|
||||
// Options returns the options of a provider
|
||||
Options() Options
|
||||
// Endpoint for the provider
|
||||
Endpoint() string
|
||||
// Redirect url incase of UI
|
||||
Redirect() string
|
||||
}
|
||||
|
||||
// Grant is a granted authorisation
|
||||
type Grant struct {
|
||||
// token for reuse
|
||||
Token string
|
||||
// Expiry of the token
|
||||
Expiry time.Time
|
||||
// Scopes associated with grant
|
||||
Scopes []string
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: auth/service/proto/auth.proto
|
||||
// source: github.com/micro/go-micro/auth/service/proto/auth.proto
|
||||
|
||||
package go_micro_auth
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
context "context"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
@@ -35,8 +35,8 @@ var _ server.Option
|
||||
|
||||
type AuthService interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error)
|
||||
Validate(ctx context.Context, in *ValidateRequest, opts ...client.CallOption) (*ValidateResponse, error)
|
||||
Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error)
|
||||
Inspect(ctx context.Context, in *InspectRequest, opts ...client.CallOption) (*InspectResponse, error)
|
||||
Token(ctx context.Context, in *TokenRequest, opts ...client.CallOption) (*TokenResponse, error)
|
||||
}
|
||||
|
||||
type authService struct {
|
||||
@@ -45,12 +45,6 @@ type authService struct {
|
||||
}
|
||||
|
||||
func NewAuthService(name string, c client.Client) AuthService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "go.micro.auth"
|
||||
}
|
||||
return &authService{
|
||||
c: c,
|
||||
name: name,
|
||||
@@ -67,9 +61,9 @@ func (c *authService) Generate(ctx context.Context, in *GenerateRequest, opts ..
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Validate(ctx context.Context, in *ValidateRequest, opts ...client.CallOption) (*ValidateResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Validate", in)
|
||||
out := new(ValidateResponse)
|
||||
func (c *authService) Inspect(ctx context.Context, in *InspectRequest, opts ...client.CallOption) (*InspectResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Inspect", in)
|
||||
out := new(InspectResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -77,9 +71,9 @@ func (c *authService) Validate(ctx context.Context, in *ValidateRequest, opts ..
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Revoke", in)
|
||||
out := new(RevokeResponse)
|
||||
func (c *authService) Token(ctx context.Context, in *TokenRequest, opts ...client.CallOption) (*TokenResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Token", in)
|
||||
out := new(TokenResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -91,15 +85,15 @@ func (c *authService) Revoke(ctx context.Context, in *RevokeRequest, opts ...cli
|
||||
|
||||
type AuthHandler interface {
|
||||
Generate(context.Context, *GenerateRequest, *GenerateResponse) error
|
||||
Validate(context.Context, *ValidateRequest, *ValidateResponse) error
|
||||
Revoke(context.Context, *RevokeRequest, *RevokeResponse) error
|
||||
Inspect(context.Context, *InspectRequest, *InspectResponse) error
|
||||
Token(context.Context, *TokenRequest, *TokenResponse) error
|
||||
}
|
||||
|
||||
func RegisterAuthHandler(s server.Server, hdlr AuthHandler, opts ...server.HandlerOption) error {
|
||||
type auth interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error
|
||||
Validate(ctx context.Context, in *ValidateRequest, out *ValidateResponse) error
|
||||
Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error
|
||||
Inspect(ctx context.Context, in *InspectRequest, out *InspectResponse) error
|
||||
Token(ctx context.Context, in *TokenRequest, out *TokenResponse) error
|
||||
}
|
||||
type Auth struct {
|
||||
auth
|
||||
@@ -116,10 +110,150 @@ func (h *authHandler) Generate(ctx context.Context, in *GenerateRequest, out *Ge
|
||||
return h.AuthHandler.Generate(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Validate(ctx context.Context, in *ValidateRequest, out *ValidateResponse) error {
|
||||
return h.AuthHandler.Validate(ctx, in, out)
|
||||
func (h *authHandler) Inspect(ctx context.Context, in *InspectRequest, out *InspectResponse) error {
|
||||
return h.AuthHandler.Inspect(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error {
|
||||
return h.AuthHandler.Revoke(ctx, in, out)
|
||||
func (h *authHandler) Token(ctx context.Context, in *TokenRequest, out *TokenResponse) error {
|
||||
return h.AuthHandler.Token(ctx, in, out)
|
||||
}
|
||||
|
||||
// Client API for Accounts service
|
||||
|
||||
type AccountsService interface {
|
||||
List(ctx context.Context, in *ListAccountsRequest, opts ...client.CallOption) (*ListAccountsResponse, error)
|
||||
}
|
||||
|
||||
type accountsService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewAccountsService(name string, c client.Client) AccountsService {
|
||||
return &accountsService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *accountsService) List(ctx context.Context, in *ListAccountsRequest, opts ...client.CallOption) (*ListAccountsResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Accounts.List", in)
|
||||
out := new(ListAccountsResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Accounts service
|
||||
|
||||
type AccountsHandler interface {
|
||||
List(context.Context, *ListAccountsRequest, *ListAccountsResponse) error
|
||||
}
|
||||
|
||||
func RegisterAccountsHandler(s server.Server, hdlr AccountsHandler, opts ...server.HandlerOption) error {
|
||||
type accounts interface {
|
||||
List(ctx context.Context, in *ListAccountsRequest, out *ListAccountsResponse) error
|
||||
}
|
||||
type Accounts struct {
|
||||
accounts
|
||||
}
|
||||
h := &accountsHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Accounts{h}, opts...))
|
||||
}
|
||||
|
||||
type accountsHandler struct {
|
||||
AccountsHandler
|
||||
}
|
||||
|
||||
func (h *accountsHandler) List(ctx context.Context, in *ListAccountsRequest, out *ListAccountsResponse) error {
|
||||
return h.AccountsHandler.List(ctx, in, out)
|
||||
}
|
||||
|
||||
// Client API for Rules service
|
||||
|
||||
type RulesService interface {
|
||||
Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error)
|
||||
Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error)
|
||||
List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error)
|
||||
}
|
||||
|
||||
type rulesService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewRulesService(name string, c client.Client) RulesService {
|
||||
return &rulesService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *rulesService) Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Rules.Create", in)
|
||||
out := new(CreateResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *rulesService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Rules.Delete", in)
|
||||
out := new(DeleteResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *rulesService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Rules.List", in)
|
||||
out := new(ListResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Rules service
|
||||
|
||||
type RulesHandler interface {
|
||||
Create(context.Context, *CreateRequest, *CreateResponse) error
|
||||
Delete(context.Context, *DeleteRequest, *DeleteResponse) error
|
||||
List(context.Context, *ListRequest, *ListResponse) error
|
||||
}
|
||||
|
||||
func RegisterRulesHandler(s server.Server, hdlr RulesHandler, opts ...server.HandlerOption) error {
|
||||
type rules interface {
|
||||
Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error
|
||||
Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error
|
||||
List(ctx context.Context, in *ListRequest, out *ListResponse) error
|
||||
}
|
||||
type Rules struct {
|
||||
rules
|
||||
}
|
||||
h := &rulesHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Rules{h}, opts...))
|
||||
}
|
||||
|
||||
type rulesHandler struct {
|
||||
RulesHandler
|
||||
}
|
||||
|
||||
func (h *rulesHandler) Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error {
|
||||
return h.RulesHandler.Create(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *rulesHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error {
|
||||
return h.RulesHandler.Delete(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *rulesHandler) List(ctx context.Context, in *ListRequest, out *ListResponse) error {
|
||||
return h.RulesHandler.List(ctx, in, out)
|
||||
}
|
||||
|
@@ -3,48 +3,128 @@ syntax = "proto3";
|
||||
package go.micro.auth;
|
||||
|
||||
service Auth {
|
||||
rpc Generate(GenerateRequest) returns (GenerateResponse) {};
|
||||
rpc Validate(ValidateRequest) returns (ValidateResponse) {};
|
||||
rpc Revoke(RevokeRequest) returns (RevokeResponse) {};
|
||||
rpc Generate(GenerateRequest) returns (GenerateResponse) {};
|
||||
rpc Inspect(InspectRequest) returns (InspectResponse) {};
|
||||
rpc Token(TokenRequest) returns (TokenResponse) {};
|
||||
}
|
||||
|
||||
message Account{
|
||||
string id = 1;
|
||||
string token = 2;
|
||||
int64 created = 3;
|
||||
int64 expiry = 4;
|
||||
repeated Role roles = 5;
|
||||
map<string, string> metadata = 6;
|
||||
service Accounts {
|
||||
rpc List(ListAccountsRequest) returns (ListAccountsResponse) {};
|
||||
}
|
||||
|
||||
message Role {
|
||||
string name = 1;
|
||||
Resource resource = 2;
|
||||
service Rules {
|
||||
rpc Create(CreateRequest) returns (CreateResponse) {};
|
||||
rpc Delete(DeleteRequest) returns (DeleteResponse) {};
|
||||
rpc List(ListRequest) returns (ListResponse) {};
|
||||
}
|
||||
|
||||
message ListAccountsRequest {
|
||||
}
|
||||
|
||||
message ListAccountsResponse {
|
||||
repeated Account accounts = 1;
|
||||
}
|
||||
|
||||
message Token {
|
||||
string token = 1;
|
||||
string type = 2;
|
||||
int64 created = 3;
|
||||
int64 expiry = 4;
|
||||
string subject = 5;
|
||||
repeated string roles = 6;
|
||||
map<string, string> metadata = 7;
|
||||
string namespace = 8;
|
||||
}
|
||||
|
||||
message Account {
|
||||
string id = 1;
|
||||
string secret = 2;
|
||||
repeated string roles = 3;
|
||||
map<string, string> metadata = 4;
|
||||
string namespace = 5;
|
||||
}
|
||||
|
||||
message Resource{
|
||||
string name = 1;
|
||||
string type = 2;
|
||||
string name = 1;
|
||||
string type = 2;
|
||||
string endpoint = 3;
|
||||
}
|
||||
|
||||
message GenerateRequest {
|
||||
Account account = 1;
|
||||
string id = 1;
|
||||
repeated string roles = 2;
|
||||
map<string, string> metadata = 3;
|
||||
string namespace = 4;
|
||||
}
|
||||
|
||||
message GenerateResponse {
|
||||
Account account = 1;
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message ValidateRequest {
|
||||
string token = 1;
|
||||
message GrantRequest {
|
||||
string role = 1;
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message ValidateResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
message GrantResponse {}
|
||||
|
||||
message RevokeRequest {
|
||||
string token = 1;
|
||||
string role = 1;
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message RevokeResponse {}
|
||||
|
||||
message InspectRequest {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message InspectResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message TokenRequest {
|
||||
string id = 1;
|
||||
string secret = 2;
|
||||
int64 token_expiry = 3;
|
||||
}
|
||||
|
||||
message TokenResponse {
|
||||
Token token = 1;
|
||||
}
|
||||
|
||||
enum Access {
|
||||
UNKNOWN = 0;
|
||||
GRANTED = 1;
|
||||
DENIED = 2;
|
||||
}
|
||||
|
||||
message Rule {
|
||||
string id = 1;
|
||||
string role = 2;
|
||||
Resource resource = 3;
|
||||
Access access = 4;
|
||||
}
|
||||
|
||||
message CreateRequest {
|
||||
string role = 1;
|
||||
Resource resource = 2;
|
||||
Access access = 3;
|
||||
}
|
||||
|
||||
message CreateResponse {}
|
||||
|
||||
message DeleteRequest {
|
||||
string role = 1;
|
||||
Resource resource = 2;
|
||||
Access access = 3;
|
||||
}
|
||||
|
||||
message DeleteResponse {}
|
||||
|
||||
message ListRequest {
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated Rule rules = 1;
|
||||
}
|
||||
|
@@ -2,11 +2,18 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
pb "github.com/micro/go-micro/v2/auth/service/proto"
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
"github.com/micro/go-micro/v2/auth/token/jwt"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/util/jitter"
|
||||
)
|
||||
|
||||
// NewAuth returns a new instance of the Auth service
|
||||
@@ -20,113 +27,253 @@ func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
type svc struct {
|
||||
options auth.Options
|
||||
auth pb.AuthService
|
||||
rule pb.RulesService
|
||||
jwt token.Provider
|
||||
|
||||
rules []*pb.Rule
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (s *svc) String() string {
|
||||
return "service"
|
||||
}
|
||||
|
||||
func (s *svc) Init(opts ...auth.Option) error {
|
||||
func (s *svc) Init(opts ...auth.Option) {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
|
||||
dc := client.DefaultClient
|
||||
s.auth = pb.NewAuthService("go.micro.auth", dc)
|
||||
s.rule = pb.NewRulesService("go.micro.auth", dc)
|
||||
|
||||
return nil
|
||||
// if we have a JWT public key passed as an option,
|
||||
// we can decode tokens with the type "JWT" locally
|
||||
// and not have to make an RPC call
|
||||
if key := s.options.PublicKey; len(key) > 0 {
|
||||
s.jwt = jwt.NewTokenProvider(token.WithPublicKey(key))
|
||||
}
|
||||
|
||||
// load rules periodically from the auth service
|
||||
timer := time.NewTicker(time.Second * 30)
|
||||
go func() {
|
||||
// load rules immediately on startup
|
||||
s.loadRules()
|
||||
|
||||
for {
|
||||
<-timer.C
|
||||
|
||||
// jitter for up to 5 seconds, this stops
|
||||
// all the services calling the auth service
|
||||
// at the exact same time
|
||||
time.Sleep(jitter.Do(time.Second * 5))
|
||||
s.loadRules()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *svc) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
// Generate a new auth account
|
||||
// Generate a new account
|
||||
func (s *svc) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// construct the request
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
sa := &auth.Account{
|
||||
Id: id,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
}
|
||||
req := &pb.GenerateRequest{Account: serializeAccount(sa)}
|
||||
|
||||
// execute the request
|
||||
resp, err := s.auth.Generate(context.Background(), req)
|
||||
rsp, err := s.auth.Generate(context.TODO(), &pb.GenerateRequest{
|
||||
Id: id,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
Namespace: options.Namespace,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// format the response
|
||||
return deserializeAccount(resp.Account), nil
|
||||
return serializeAccount(rsp.Account), nil
|
||||
}
|
||||
|
||||
// Revoke an authorization account
|
||||
func (s *svc) Revoke(token string) error {
|
||||
// contruct the request
|
||||
req := &pb.RevokeRequest{Token: token}
|
||||
|
||||
// execute the request
|
||||
_, err := s.auth.Revoke(context.Background(), req)
|
||||
// Grant access to a resource
|
||||
func (s *svc) Grant(role string, res *auth.Resource) error {
|
||||
_, err := s.rule.Create(context.TODO(), &pb.CreateRequest{
|
||||
Role: role,
|
||||
Access: pb.Access_GRANTED,
|
||||
Resource: &pb.Resource{
|
||||
Type: res.Type,
|
||||
Name: res.Name,
|
||||
Endpoint: res.Endpoint,
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate an account token
|
||||
func (s *svc) Validate(token string) (*auth.Account, error) {
|
||||
resp, err := s.auth.Validate(context.Background(), &pb.ValidateRequest{Token: token})
|
||||
// Revoke access to a resource
|
||||
func (s *svc) Revoke(role string, res *auth.Resource) error {
|
||||
_, err := s.rule.Delete(context.TODO(), &pb.DeleteRequest{
|
||||
Role: role,
|
||||
Access: pb.Access_GRANTED,
|
||||
Resource: &pb.Resource{
|
||||
Type: res.Type,
|
||||
Name: res.Name,
|
||||
Endpoint: res.Endpoint,
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify an account has access to a resource
|
||||
func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error {
|
||||
queries := [][]string{
|
||||
{res.Type, res.Name, res.Endpoint}, // check for specific role, e.g. service.foo.ListFoo:admin (role is checked in accessForRule)
|
||||
{res.Type, res.Name, "*"}, // check for wildcard endpoint, e.g. service.foo*
|
||||
{res.Type, "*"}, // check for wildcard name, e.g. service.*
|
||||
{"*"}, // check for wildcard type, e.g. *
|
||||
}
|
||||
|
||||
// endpoint is a url which can have wildcard excludes, e.g.
|
||||
// "/foo/*" will allow "/foo/bar"
|
||||
if comps := strings.Split(res.Endpoint, "/"); len(comps) > 1 {
|
||||
for i := 1; i < len(comps); i++ {
|
||||
wildcard := fmt.Sprintf("%v/*", strings.Join(comps[0:i], "/"))
|
||||
queries = append(queries, []string{res.Type, res.Name, wildcard})
|
||||
}
|
||||
}
|
||||
|
||||
for _, q := range queries {
|
||||
for _, rule := range s.listRules(q...) {
|
||||
switch accessForRule(rule, acc, res) {
|
||||
case pb.Access_UNKNOWN:
|
||||
continue // rule did not specify access, check the next rule
|
||||
case pb.Access_GRANTED:
|
||||
log.Infof("%v granted access to %v:%v:%v by rule %v", acc.ID, res.Type, res.Name, res.Endpoint, rule.Id)
|
||||
return nil // rule grants the account access to the resource
|
||||
case pb.Access_DENIED:
|
||||
log.Infof("%v denied access to %v:%v:%v by rule %v", acc.ID, res.Type, res.Name, res.Endpoint, rule.Id)
|
||||
return auth.ErrForbidden // rule denies access to the resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no rules were found for the resource, default to denying access
|
||||
log.Infof("%v denied access to %v:%v:%v by lack of rule (%v rules found)", acc.ID, res.Type, res.Name, res.Endpoint, len(s.rules))
|
||||
return auth.ErrForbidden
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (s *svc) Inspect(token string) (*auth.Account, error) {
|
||||
// try to decode JWT locally and fall back to srv if an error
|
||||
// occurs, TODO: find a better way of determining if the token
|
||||
// is a JWT, possibly update the interface to take an auth.Token
|
||||
// and not just the string
|
||||
if len(strings.Split(token, ".")) == 3 && s.jwt != nil {
|
||||
if tok, err := s.jwt.Inspect(token); err == nil {
|
||||
return &auth.Account{
|
||||
ID: tok.Subject,
|
||||
Roles: tok.Roles,
|
||||
Metadata: tok.Metadata,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{
|
||||
Token: token,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return deserializeAccount(resp.Account), nil
|
||||
return serializeAccount(rsp.Account), nil
|
||||
}
|
||||
|
||||
func serializeAccount(sa *auth.Account) *pb.Account {
|
||||
roles := make([]*pb.Role, len(sa.Roles))
|
||||
for i, r := range sa.Roles {
|
||||
roles[i] = &pb.Role{
|
||||
Name: r.Name,
|
||||
// Token generation using an account ID and secret
|
||||
func (s *svc) Token(id, secret string, opts ...auth.TokenOption) (*auth.Token, error) {
|
||||
options := auth.NewTokenOptions(opts...)
|
||||
|
||||
rsp, err := s.auth.Token(context.Background(), &pb.TokenRequest{
|
||||
Id: id,
|
||||
Secret: secret,
|
||||
TokenExpiry: int64(options.TokenExpiry.Seconds()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serializeToken(rsp.Token), nil
|
||||
}
|
||||
|
||||
var ruleJoinKey = ":"
|
||||
|
||||
// accessForRule returns a rule status, indicating if a rule permits access to a
|
||||
// resource for a given account
|
||||
func accessForRule(rule *pb.Rule, acc *auth.Account, res *auth.Resource) pb.Access {
|
||||
if rule.Role == "*" {
|
||||
return rule.Access
|
||||
}
|
||||
|
||||
for _, role := range acc.Roles {
|
||||
if rule.Role == role {
|
||||
return rule.Access
|
||||
}
|
||||
|
||||
if r.Resource != nil {
|
||||
roles[i].Resource = &pb.Resource{
|
||||
Name: r.Resource.Name,
|
||||
Type: r.Resource.Type,
|
||||
}
|
||||
// allow user.anything if role is user.*
|
||||
if strings.HasSuffix(rule.Role, ".*") && strings.HasPrefix(rule.Role, role+".") {
|
||||
return rule.Access
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.Account{
|
||||
Id: sa.Id,
|
||||
Roles: roles,
|
||||
Metadata: sa.Metadata,
|
||||
return pb.Access_UNKNOWN
|
||||
}
|
||||
|
||||
// listRules gets all the rules from the store which have an id
|
||||
// prefix matching the filters
|
||||
func (s *svc) listRules(filters ...string) []*pb.Rule {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
prefix := strings.Join(filters, ruleJoinKey)
|
||||
|
||||
var rules []*pb.Rule
|
||||
for _, r := range s.rules {
|
||||
if strings.HasPrefix(r.Id, prefix) {
|
||||
rules = append(rules, r)
|
||||
}
|
||||
}
|
||||
|
||||
return rules
|
||||
}
|
||||
|
||||
// loadRules retrieves the rules from the auth service
|
||||
func (s *svc) loadRules() {
|
||||
rsp, err := s.rule.List(context.TODO(), &pb.ListRequest{})
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Error listing rules: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
s.rules = rsp.Rules
|
||||
}
|
||||
|
||||
func serializeToken(t *pb.Token) *auth.Token {
|
||||
return &auth.Token{
|
||||
Token: t.Token,
|
||||
Type: t.Type,
|
||||
Created: time.Unix(t.Created, 0),
|
||||
Expiry: time.Unix(t.Expiry, 0),
|
||||
Subject: t.Subject,
|
||||
Roles: t.Roles,
|
||||
Metadata: t.Metadata,
|
||||
}
|
||||
}
|
||||
|
||||
func deserializeAccount(a *pb.Account) *auth.Account {
|
||||
// format the response
|
||||
sa := &auth.Account{
|
||||
Id: a.Id,
|
||||
Token: a.Token,
|
||||
Created: time.Unix(a.Created, 0),
|
||||
Expiry: time.Unix(a.Expiry, 0),
|
||||
Metadata: a.Metadata,
|
||||
func serializeAccount(a *pb.Account) *auth.Account {
|
||||
return &auth.Account{
|
||||
ID: a.Id,
|
||||
Roles: a.Roles,
|
||||
Metadata: a.Metadata,
|
||||
Namespace: a.Namespace,
|
||||
Secret: a.Secret,
|
||||
}
|
||||
|
||||
sa.Roles = make([]*auth.Role, len(a.Roles))
|
||||
for i, r := range a.Roles {
|
||||
sa.Roles[i] = &auth.Role{
|
||||
Name: r.Name,
|
||||
}
|
||||
|
||||
if r.Resource != nil {
|
||||
sa.Roles[i].Resource = &auth.Resource{
|
||||
Name: r.Resource.Name,
|
||||
Type: r.Resource.Type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sa
|
||||
}
|
||||
|
@@ -1,128 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
// NewAuth returns an instance of store auth
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
options := auth.Options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
return &Auth{
|
||||
store: store.DefaultStore,
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
store store.Store
|
||||
opts auth.Options
|
||||
}
|
||||
|
||||
// Init the auth package
|
||||
func (a *Auth) Init(opts ...auth.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&a.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Options returns the options set
|
||||
func (a *Auth) Options() auth.Options {
|
||||
return a.opts
|
||||
}
|
||||
|
||||
// Generate a new auth Account
|
||||
func (a *Auth) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// generate the token
|
||||
token, err := uuid.NewUUID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the options
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
|
||||
// construct the account
|
||||
sa := auth.Account{
|
||||
Id: id,
|
||||
Token: token.String(),
|
||||
Created: time.Now(),
|
||||
Metadata: options.Metadata,
|
||||
Roles: options.Roles,
|
||||
}
|
||||
|
||||
// encode the data to bytes
|
||||
buf := &bytes.Buffer{}
|
||||
e := gob.NewEncoder(buf)
|
||||
if err := e.Encode(sa); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// write to the store
|
||||
err = a.store.Write(&store.Record{
|
||||
Key: token.String(),
|
||||
Value: buf.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return the result
|
||||
return &sa, nil
|
||||
}
|
||||
|
||||
// Revoke an authorization Account
|
||||
func (a *Auth) Revoke(token string) error {
|
||||
records, err := a.store.Read(token, store.ReadSuffix())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(records) == 0 {
|
||||
return errors.BadRequest("go.micro.auth", "token not found")
|
||||
}
|
||||
|
||||
for _, r := range records {
|
||||
if err := a.store.Delete(r.Key); err != nil {
|
||||
return errors.InternalServerError("go.micro.auth", "error deleting from store")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate an account token
|
||||
func (a *Auth) Validate(token string) (*auth.Account, error) {
|
||||
// lookup the record by token
|
||||
records, err := a.store.Read(token, store.ReadSuffix())
|
||||
if err == store.ErrNotFound || len(records) == 0 {
|
||||
return nil, errors.Unauthorized("go.micro.auth", "invalid token")
|
||||
} else if err != nil {
|
||||
return nil, errors.InternalServerError("go.micro.auth", "error reading store")
|
||||
}
|
||||
|
||||
// decode the result
|
||||
b := bytes.NewBuffer(records[0].Value)
|
||||
decoder := gob.NewDecoder(b)
|
||||
var sa auth.Account
|
||||
err = decoder.Decode(&sa)
|
||||
|
||||
// return the result
|
||||
return &sa, err
|
||||
}
|
||||
|
||||
// String returns the implementation
|
||||
func (a *Auth) String() string {
|
||||
return "store"
|
||||
}
|
102
auth/token/basic/basic.go
Normal file
102
auth/token/basic/basic.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
// Basic implementation of token provider, backed by the store
|
||||
type Basic struct {
|
||||
store store.Store
|
||||
}
|
||||
|
||||
var (
|
||||
// StorePrefix to isolate tokens
|
||||
StorePrefix = "tokens/"
|
||||
)
|
||||
|
||||
// NewTokenProvider returns an initialized basic provider
|
||||
func NewTokenProvider(opts ...token.Option) token.Provider {
|
||||
options := token.NewOptions(opts...)
|
||||
|
||||
if options.Store == nil {
|
||||
options.Store = store.DefaultStore
|
||||
}
|
||||
|
||||
return &Basic{
|
||||
store: options.Store,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a token for an account
|
||||
func (b *Basic) Generate(subject string, opts ...token.GenerateOption) (*auth.Token, error) {
|
||||
options := token.NewGenerateOptions(opts...)
|
||||
|
||||
// construct the token
|
||||
token := auth.Token{
|
||||
Subject: subject,
|
||||
Type: b.String(),
|
||||
Token: uuid.New().String(),
|
||||
Created: time.Now(),
|
||||
Expiry: time.Now().Add(options.Expiry),
|
||||
Metadata: options.Metadata,
|
||||
Roles: options.Roles,
|
||||
Namespace: options.Namespace,
|
||||
}
|
||||
|
||||
// marshal the account to bytes
|
||||
bytes, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// write to the store
|
||||
err = b.store.Write(&store.Record{
|
||||
Key: fmt.Sprintf("%v%v", StorePrefix, token.Token),
|
||||
Value: bytes,
|
||||
Expiry: options.Expiry,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return the token
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
// Inspect a token
|
||||
func (b *Basic) Inspect(t string) (*auth.Token, error) {
|
||||
// lookup the token in the store
|
||||
recs, err := b.store.Read(StorePrefix + t)
|
||||
if err == store.ErrNotFound {
|
||||
return nil, token.ErrInvalidToken
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes := recs[0].Value
|
||||
|
||||
// unmarshal the bytes
|
||||
var tok *auth.Token
|
||||
if err := json.Unmarshal(bytes, &tok); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ensure the token hasn't expired, the store should
|
||||
// expire the token but we're checking again
|
||||
if tok.Expiry.Unix() < time.Now().Unix() {
|
||||
return nil, token.ErrInvalidToken
|
||||
}
|
||||
|
||||
return tok, err
|
||||
}
|
||||
|
||||
// String returns basic
|
||||
func (b *Basic) String() string {
|
||||
return "basic"
|
||||
}
|
80
auth/token/basic/basic_test.go
Normal file
80
auth/token/basic/basic_test.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
"github.com/micro/go-micro/v2/store/memory"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
store := memory.NewStore()
|
||||
b := NewTokenProvider(token.WithStore(store))
|
||||
|
||||
_, err := b.Generate("test")
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
recs, err := store.List()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read from store: %v", err)
|
||||
}
|
||||
if len(recs) != 1 {
|
||||
t.Errorf("Generate didn't write to the store, expected 1 record, got %v", len(recs))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInspect(t *testing.T) {
|
||||
store := memory.NewStore()
|
||||
b := NewTokenProvider(token.WithStore(store))
|
||||
|
||||
t.Run("Valid token", func(t *testing.T) {
|
||||
md := map[string]string{"foo": "bar"}
|
||||
roles := []string{"admin"}
|
||||
subject := "test"
|
||||
|
||||
opts := []token.GenerateOption{
|
||||
token.WithMetadata(md),
|
||||
token.WithRoles(roles...),
|
||||
}
|
||||
|
||||
tok, err := b.Generate(subject, opts...)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
tok2, err := b.Inspect(tok.Token)
|
||||
if err != nil {
|
||||
t.Fatalf("Inspect returned %v error, expected nil", err)
|
||||
}
|
||||
if tok2.Subject != subject {
|
||||
t.Errorf("Inspect returned %v as the token subject, expected %v", tok2.Subject, subject)
|
||||
}
|
||||
if len(tok2.Roles) != len(roles) {
|
||||
t.Errorf("Inspect returned %v roles, expected %v", len(tok2.Roles), len(roles))
|
||||
}
|
||||
if len(tok2.Metadata) != len(md) {
|
||||
t.Errorf("Inspect returned %v as the token metadata, expected %v", tok2.Metadata, md)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Expired token", func(t *testing.T) {
|
||||
tok, err := b.Generate("foo", token.WithExpiry(-10*time.Second))
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
if _, err = b.Inspect(tok.Token); err != token.ErrInvalidToken {
|
||||
t.Fatalf("Inspect returned %v error, expected %v", err, token.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid token", func(t *testing.T) {
|
||||
_, err := b.Inspect("Invalid token")
|
||||
if err != token.ErrInvalidToken {
|
||||
t.Fatalf("Inspect returned %v error, expected %v", err, token.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
}
|
114
auth/token/jwt/jwt.go
Normal file
114
auth/token/jwt/jwt.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
)
|
||||
|
||||
// authClaims to be encoded in the JWT
|
||||
type authClaims struct {
|
||||
Roles []string `json:"roles"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
Namespace string `json:"namespace"`
|
||||
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// JWT implementation of token provider
|
||||
type JWT struct {
|
||||
opts token.Options
|
||||
}
|
||||
|
||||
// NewTokenProvider returns an initialized basic provider
|
||||
func NewTokenProvider(opts ...token.Option) token.Provider {
|
||||
return &JWT{
|
||||
opts: token.NewOptions(opts...),
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a new JWT
|
||||
func (j *JWT) Generate(subject string, opts ...token.GenerateOption) (*auth.Token, error) {
|
||||
// decode the private key
|
||||
priv, err := base64.StdEncoding.DecodeString(j.opts.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the private key
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM(priv)
|
||||
if err != nil {
|
||||
return nil, token.ErrEncodingToken
|
||||
}
|
||||
|
||||
// parse the options
|
||||
options := token.NewGenerateOptions(opts...)
|
||||
|
||||
// generate the JWT
|
||||
expiry := time.Now().Add(options.Expiry)
|
||||
t := jwt.NewWithClaims(jwt.SigningMethodRS256, authClaims{
|
||||
options.Roles, options.Metadata, options.Namespace, jwt.StandardClaims{
|
||||
Subject: subject,
|
||||
ExpiresAt: expiry.Unix(),
|
||||
},
|
||||
})
|
||||
tok, err := t.SignedString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return the token
|
||||
return &auth.Token{
|
||||
Subject: subject,
|
||||
Token: tok,
|
||||
Type: j.String(),
|
||||
Created: time.Now(),
|
||||
Expiry: expiry,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
Namespace: options.Namespace,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Inspect a JWT
|
||||
func (j *JWT) Inspect(t string) (*auth.Token, error) {
|
||||
// decode the public key
|
||||
pub, err := base64.StdEncoding.DecodeString(j.opts.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the public key
|
||||
res, err := jwt.ParseWithClaims(t, &authClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwt.ParseRSAPublicKeyFromPEM(pub)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, token.ErrInvalidToken
|
||||
}
|
||||
|
||||
// validate the token
|
||||
if !res.Valid {
|
||||
return nil, token.ErrInvalidToken
|
||||
}
|
||||
claims, ok := res.Claims.(*authClaims)
|
||||
if !ok {
|
||||
return nil, token.ErrInvalidToken
|
||||
}
|
||||
|
||||
// return the token
|
||||
return &auth.Token{
|
||||
Token: t,
|
||||
Subject: claims.Subject,
|
||||
Metadata: claims.Metadata,
|
||||
Roles: claims.Roles,
|
||||
Namespace: claims.Namespace,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// String returns JWT
|
||||
func (j *JWT) String() string {
|
||||
return "jwt"
|
||||
}
|
90
auth/token/jwt/jwt_test.go
Normal file
90
auth/token/jwt/jwt_test.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth/token"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
privKey, err := ioutil.ReadFile("test/sample_key")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read private key: %v", err)
|
||||
}
|
||||
|
||||
j := NewTokenProvider(
|
||||
token.WithPrivateKey(string(privKey)),
|
||||
)
|
||||
|
||||
_, err = j.Generate("test")
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInspect(t *testing.T) {
|
||||
pubKey, err := ioutil.ReadFile("test/sample_key.pub")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read public key: %v", err)
|
||||
}
|
||||
privKey, err := ioutil.ReadFile("test/sample_key")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to read private key: %v", err)
|
||||
}
|
||||
|
||||
j := NewTokenProvider(
|
||||
token.WithPublicKey(string(pubKey)),
|
||||
token.WithPrivateKey(string(privKey)),
|
||||
)
|
||||
|
||||
t.Run("Valid token", func(t *testing.T) {
|
||||
md := map[string]string{"foo": "bar"}
|
||||
roles := []string{"admin"}
|
||||
subject := "test"
|
||||
|
||||
opts := []token.GenerateOption{
|
||||
token.WithMetadata(md),
|
||||
token.WithRoles(roles...),
|
||||
}
|
||||
|
||||
tok, err := j.Generate(subject, opts...)
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
tok2, err := j.Inspect(tok.Token)
|
||||
if err != nil {
|
||||
t.Fatalf("Inspect returned %v error, expected nil", err)
|
||||
}
|
||||
if tok2.Subject != subject {
|
||||
t.Errorf("Inspect returned %v as the token subject, expected %v", tok2.Subject, subject)
|
||||
}
|
||||
if len(tok2.Roles) != len(roles) {
|
||||
t.Errorf("Inspect returned %v roles, expected %v", len(tok2.Roles), len(roles))
|
||||
}
|
||||
if len(tok2.Metadata) != len(md) {
|
||||
t.Errorf("Inspect returned %v as the token metadata, expected %v", tok2.Metadata, md)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Expired token", func(t *testing.T) {
|
||||
tok, err := j.Generate("foo", token.WithExpiry(-10*time.Second))
|
||||
if err != nil {
|
||||
t.Fatalf("Generate returned %v error, expected nil", err)
|
||||
}
|
||||
|
||||
if _, err = j.Inspect(tok.Token); err != token.ErrInvalidToken {
|
||||
t.Fatalf("Inspect returned %v error, expected %v", err, token.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid token", func(t *testing.T) {
|
||||
_, err := j.Inspect("Invalid token")
|
||||
if err != token.ErrInvalidToken {
|
||||
t.Fatalf("Inspect returned %v error, expected %v", err, token.ErrInvalidToken)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
1
auth/token/jwt/test/sample_key
Normal file
1
auth/token/jwt/test/sample_key
Normal file
@@ -0,0 +1 @@
|
||||
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS3dJQkFBS0NBZ0VBOFNiSlA1WGJFaWRSbTViMnNOcExHbzJlV2ZVNU9KZTBpemdySHdEOEg3RjZQa1BkCi9SbDkvMXBNVjdNaU8zTEh3dGhIQzJCUllxcisxd0Zkb1pDR0JZckxhWHVYRnFLMHZ1WmhQcUUzYXpqdUlIUXUKMEJIL2xYUU1xeUVxRjVNSTJ6ZWpDNHpNenIxNU9OK2dFNEpuaXBqcC9DZGpPUEFEbUpHK0JKOXFlRS9RUGVtLwptVWRJVC9MYUY3a1F4eVlLNVZLbitOZ09Xek1sektBQXBDbjdUVEtCVWU4RlpHNldTWDdMVjBlTEdIc29pYnhsCm85akRqbFk1b0JPY3pmcWVOV0hLNUdYQjdRd3BMTmg5NDZQelpucW9hcFdVZStZL1JPaUhpekpUY3I1Wk1TTDUKd2xFcThoTmhtaG01Tk5lL08rR2dqQkROU2ZVaDA2K3E0bmdtYm1OWDVoODM4QmJqUmN5YzM2ZHd6NkpVK2R1bwpSdFFoZ2lZOTEwcFBmOWJhdVhXcXdVQ1VhNHFzSHpqS1IwTC9OMVhYQXlsQ0RqeWVnWnp6Y093MkNIOFNrZkZVCnJnTHJQYkVCOWVnY0drMzgrYnBLczNaNlJyNSt0bkQxQklQSUZHTGVJMFVPQzAreGlCdjBvenhJRE9GbldhOVUKVEdEeFV4OG9qOFZJZVJuV0RxNk1jMWlKcDhVeWNpQklUUnR3NGRabzcweG1mbmVJV3pyM0tTTmFoU29nSmRSMApsYVF6QXVQM2FpV1hJTXAyc2M4U2MrQmwrTGpYbUJveEJyYUJIaDlLa0pKRWNnQUZ3czJib2pDbEpPWXhvRi9YCmdGS1NzSW5IRHJIVk95V1BCZTNmYWRFYzc3YituYi9leE96cjFFcnhoR2c5akZtcmtPK3M0eEdodjZNQ0F3RUEKQVFLQ0FnRUFqUzc1Q2VvUlRRcUtBNzZaaFNiNGEzNVlKRENtcEpSazFsRTNKYnFzNFYxRnhXaDBjZmJYeG9VMgpSdTRRYjUrZWhsdWJGSFQ2a1BxdG9uRWhRVExjMUNmVE9WbHJOb3hocDVZM2ZyUmlQcnNnNXcwK1R3RUtrcFJUCnltanJQTXdQbGxCM2U0NmVaYmVXWGc3R3FFVmptMGcxVFRRK0tocVM4R0w3VGJlTFhRN1ZTem9ydTNCNVRKMVEKeEN6TVB0dnQ2eDYrU3JrcmhvZG1iT3VNRkpDam1TbWxmck9pZzQ4Zkc3NUpERHRObXpLWHBEUVJpYUNodFJhVQpQRHpmUTlTamhYdFFqdkZvWFFFT3BqdkZVRjR2WldNUWNQNUw1VklDM3JRSWp4MFNzQTN6S0FwakVUbjJHNjN2CktZby8zVWttbzhkUCtGRHA3NCs5a3pLNHFFaFJycEl3bEtiN0VOZWtDUXZqUFl1K3pyKzMyUXdQNTJ2L2FveWQKdjJJaUY3M2laTU1vZDhhYjJuQStyVEI2T0cvOVlSYk5kV21tay9VTi9jUHYrN214TmZ6Y1d1ZU1XcThxMXh4eAptNTNpR0NSQ29PQ1lDQk4zcUFkb1JwYW5xd3lCOUxrLzFCQjBHUld3MjgxK3VhNXNYRnZBVDBKeTVURnduMncvClU1MlJKWFlNOXVhMFBvd214b0RDUWRuNFZYVkdNZGdXaHN4aXhHRlYwOUZObWJJQWJaN0xaWGtkS1gzc1ZVbTcKWU1WYWIzVVo2bEhtdXYzT1NzcHNVUlRqN1hiRzZpaVVlaDU1aW91OENWbnRndWtFcnEzQTQwT05FVzhjNDBzOQphVTBGaSs4eWZpQTViaVZHLzF0bWlucUVERkhuQStnWk1xNEhlSkZxcWZxaEZKa1JwRGtDZ2dFQkFQeGR1NGNKCm5Da1duZDdPWFlHMVM3UDdkVWhRUzgwSDlteW9uZFc5bGFCQm84RWRPeTVTZzNOUmsxQ2pNZFZ1a3FMcjhJSnkKeStLWk15SVpvSlJvbllaMEtIUUVMR3ZLbzFOS2NLQ1FJbnYvWHVCdFJpRzBVb1pQNVkwN0RpRFBRQWpYUjlXUwpBc0EzMmQ1eEtFOC91Y3h0MjVQVzJFakNBUmtVeHQ5d0tKazN3bC9JdXVYRlExTDdDWjJsOVlFUjlHeWxUbzhNCmxXUEY3YndtUFV4UVNKaTNVS0FjTzZweTVUU1lkdWQ2aGpQeXJwSXByNU42VGpmTlRFWkVBeU9LbXVpOHVkUkoKMUg3T3RQVEhGZElKQjNrNEJnRDZtRE1HbjB2SXBLaDhZN3NtRUZBbFkvaXlCZjMvOHk5VHVMb1BycEdqR3RHbgp4Y2RpMHFud2p0SGFNbFVDZ2dFQkFQU2Z0dVFCQ2dTU2JLUSswUEFSR2VVeEQyTmlvZk1teENNTmdHUzJ5Ull3CjRGaGV4ZWkwMVJoaFk1NjE3UjduR1dzb0czd1RQa3dvRTJtbE1aQkoxeWEvUU9RRnQ3WG02OVl0RGh0T2FWbDgKL0o4dlVuSTBtWmxtT2pjTlRoYnVPZDlNSDlRdGxIRUMxMlhYdHJNb3Fsb0U2a05TT0pJalNxYm9wcDRXc1BqcApvZTZ0Nkdyd1RhOHBHeUJWWS90Mi85Ym5ORHVPVlpjODBaODdtY2gzcDNQclBqU3h5di9saGxYMFMwYUdHTkhTCk1XVjdUa25OaGo1TWlIRXFnZ1pZemtBWTkyd1JoVENnU1A2M0VNcitUWXFudXVuMXJHbndPYm95TDR2aFRpV0UKcU42UDNCTFlCZ1FpMllDTDludEJrOEl6RHZyd096dW5GVnhhZ0g5SVVoY0NnZ0VCQUwzQXlLa1BlOENWUmR6cQpzL284VkJDZmFSOFhhUGRnSGxTek1BSXZpNXEwNENqckRyMlV3MHZwTVdnM1hOZ0xUT3g5bFJpd3NrYk9SRmxHCmhhd3hRUWlBdkk0SE9WTlBTU0R1WHVNTG5USTQ0S0RFNlMrY2cxU0VMS2pWbDVqcDNFOEpkL1RJMVpLc0xBQUsKZTNHakM5UC9ZbE8xL21ndW4xNjVkWk01cFAwWHBPb2FaeFV2RHFFTktyekR0V1g0RngyOTZlUzdaSFJodFpCNwovQ2t1VUhlcmxrN2RDNnZzdWhTaTh2eTM3c0tPbmQ0K3c4cVM4czhZYVZxSDl3ZzVScUxxakp0bmJBUnc3alVDCm9KQ053M1hNdnc3clhaYzRTbnhVQUNMRGJNV2lLQy9xL1ZGWW9oTEs2WkpUVkJscWd5cjBSYzBRWmpDMlNJb0kKMjRwRWt3VUNnZ0VCQUpqb0FJVVNsVFY0WlVwaExXN3g4WkxPa01UWjBVdFFyd2NPR0hSYndPUUxGeUNGMVFWNQppejNiR2s4SmZyZHpVdk1sTmREZm9uQXVHTHhQa3VTVEUxWlg4L0xVRkJveXhyV3dvZ0cxaUtwME11QTV6em90CjROai9DbUtCQVkvWnh2anA5M2RFS21aZGxWQkdmeUFMeWpmTW5MWUovZXh5L09YSnhPUktZTUttSHg4M08zRWsKMWhvb0FwbTZabTIzMjRGME1iVU1ham5Idld2ZjhHZGJTNk5zcHd4L0dkbk1tYVMrdUJMVUhVMkNLbmc1bEIwVAp4OWJITmY0dXlPbTR0dXRmNzhCd1R5V3UreEdrVW0zZ2VZMnkvR1hqdDZyY2l1ajFGNzFDenZzcXFmZThTcDdJCnd6SHdxcTNzVHR5S2lCYTZuYUdEYWpNR1pKYSt4MVZJV204Q2dnRUJBT001ajFZR25Ba0pxR0czQWJSVDIvNUMKaVVxN0loYkswOGZsSGs5a2YwUlVjZWc0ZVlKY3dIRXJVaE4rdWQyLzE3MC81dDYra0JUdTVZOUg3bkpLREtESQpoeEg5SStyamNlVkR0RVNTRkluSXdDQ1lrOHhOUzZ0cHZMV1U5b0pibGFKMlZsalV2NGRFWGVQb0hkREh1Zk9ZClVLa0lsV2E3Uit1QzNEOHF5U1JrQnFLa3ZXZ1RxcFNmTVNkc1ZTeFIzU2Q4SVhFSHFjTDNUNEtMWGtYNEdEamYKMmZOSTFpZkx6ekhJMTN3Tk5IUTVRNU9SUC9pell2QzVzZkx4U2ZIUXJiMXJZVkpKWkI5ZjVBUjRmWFpHSVFsbApjMG8xd0JmZFlqMnZxVDlpR09IQnNSSTlSL2M2RzJQcUt3aFRpSzJVR2lmVFNEUVFuUkF6b2tpQVkrbE8vUjQ9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
1
auth/token/jwt/test/sample_key.pub
Normal file
1
auth/token/jwt/test/sample_key.pub
Normal file
@@ -0,0 +1 @@
|
||||
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUE4U2JKUDVYYkVpZFJtNWIyc05wTApHbzJlV2ZVNU9KZTBpemdySHdEOEg3RjZQa1BkL1JsOS8xcE1WN01pTzNMSHd0aEhDMkJSWXFyKzF3RmRvWkNHCkJZckxhWHVYRnFLMHZ1WmhQcUUzYXpqdUlIUXUwQkgvbFhRTXF5RXFGNU1JMnplakM0ek16cjE1T04rZ0U0Sm4KaXBqcC9DZGpPUEFEbUpHK0JKOXFlRS9RUGVtL21VZElUL0xhRjdrUXh5WUs1VktuK05nT1d6TWx6S0FBcENuNwpUVEtCVWU4RlpHNldTWDdMVjBlTEdIc29pYnhsbzlqRGpsWTVvQk9jemZxZU5XSEs1R1hCN1F3cExOaDk0NlB6ClpucW9hcFdVZStZL1JPaUhpekpUY3I1Wk1TTDV3bEVxOGhOaG1obTVOTmUvTytHZ2pCRE5TZlVoMDYrcTRuZ20KYm1OWDVoODM4QmJqUmN5YzM2ZHd6NkpVK2R1b1J0UWhnaVk5MTBwUGY5YmF1WFdxd1VDVWE0cXNIempLUjBMLwpOMVhYQXlsQ0RqeWVnWnp6Y093MkNIOFNrZkZVcmdMclBiRUI5ZWdjR2szOCticEtzM1o2UnI1K3RuRDFCSVBJCkZHTGVJMFVPQzAreGlCdjBvenhJRE9GbldhOVVUR0R4VXg4b2o4VkllUm5XRHE2TWMxaUpwOFV5Y2lCSVRSdHcKNGRabzcweG1mbmVJV3pyM0tTTmFoU29nSmRSMGxhUXpBdVAzYWlXWElNcDJzYzhTYytCbCtMalhtQm94QnJhQgpIaDlLa0pKRWNnQUZ3czJib2pDbEpPWXhvRi9YZ0ZLU3NJbkhEckhWT3lXUEJlM2ZhZEVjNzdiK25iL2V4T3pyCjFFcnhoR2c5akZtcmtPK3M0eEdodjZNQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo=
|
105
auth/token/options.go
Normal file
105
auth/token/options.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
// Store to persist the tokens
|
||||
Store store.Store
|
||||
// PublicKey base64 encoded, used by JWT
|
||||
PublicKey string
|
||||
// PrivateKey base64 encoded, used by JWT
|
||||
PrivateKey string
|
||||
}
|
||||
|
||||
type Option func(o *Options)
|
||||
|
||||
// WithStore sets the token providers store
|
||||
func WithStore(s store.Store) Option {
|
||||
return func(o *Options) {
|
||||
o.Store = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithPublicKey sets the JWT public key
|
||||
func WithPublicKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PublicKey = key
|
||||
}
|
||||
}
|
||||
|
||||
// WithPrivateKey sets the JWT private key
|
||||
func WithPrivateKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PrivateKey = key
|
||||
}
|
||||
}
|
||||
|
||||
func NewOptions(opts ...Option) Options {
|
||||
var options Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
//set default store
|
||||
if options.Store == nil {
|
||||
options.Store = store.DefaultStore
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
type GenerateOptions struct {
|
||||
// Expiry for the token
|
||||
Expiry time.Duration
|
||||
// Metadata associated with the account
|
||||
Metadata map[string]string
|
||||
// Roles/scopes associated with the account
|
||||
Roles []string
|
||||
// Namespace the account belongs too
|
||||
Namespace string
|
||||
}
|
||||
|
||||
type GenerateOption func(o *GenerateOptions)
|
||||
|
||||
// WithExpiry for the generated account's token expires
|
||||
func WithExpiry(d time.Duration) GenerateOption {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Expiry = d
|
||||
}
|
||||
}
|
||||
|
||||
// WithMetadata for the token
|
||||
func WithMetadata(md map[string]string) func(o *GenerateOptions) {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Metadata = md
|
||||
}
|
||||
}
|
||||
|
||||
// WithRoles for the token
|
||||
func WithRoles(rs ...string) func(o *GenerateOptions) {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Roles = rs
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace for the token
|
||||
func WithNamespace(n string) func(o *GenerateOptions) {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Namespace = n
|
||||
}
|
||||
}
|
||||
|
||||
// NewGenerateOptions from a slice of options
|
||||
func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
|
||||
var options GenerateOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
//set default Expiry of token
|
||||
if options.Expiry == 0 {
|
||||
options.Expiry = time.Minute * 15
|
||||
}
|
||||
return options
|
||||
}
|
23
auth/token/token.go
Normal file
23
auth/token/token.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotFound is returned when a token cannot be found
|
||||
ErrNotFound = errors.New("token not found")
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
ErrEncodingToken = errors.New("error encoding the token")
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
ErrInvalidToken = errors.New("invalid token provided")
|
||||
)
|
||||
|
||||
// Provider generates and inspects tokens
|
||||
type Provider interface {
|
||||
Generate(subject string, opts ...GenerateOption) (*auth.Token, error)
|
||||
Inspect(token string) (*auth.Token, error)
|
||||
String() string
|
||||
}
|
@@ -28,6 +28,7 @@ type Event interface {
|
||||
Topic() string
|
||||
Message() *Message
|
||||
Ack() error
|
||||
Error() error
|
||||
}
|
||||
|
||||
// Subscriber is a convenience return type for the Subscribe method
|
||||
|
@@ -11,7 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/codec/json"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/util/addr"
|
||||
"github.com/nats-io/nats-server/v2/server"
|
||||
@@ -53,8 +53,9 @@ type subscriber struct {
|
||||
}
|
||||
|
||||
type publication struct {
|
||||
t string
|
||||
m *Message
|
||||
t string
|
||||
err error
|
||||
m *Message
|
||||
}
|
||||
|
||||
func (p *publication) Topic() string {
|
||||
@@ -70,6 +71,10 @@ func (p *publication) Ack() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *publication) Error() error {
|
||||
return p.err
|
||||
}
|
||||
|
||||
func (s *subscriber) Options() SubscribeOptions {
|
||||
return s.opts
|
||||
}
|
||||
@@ -167,7 +172,9 @@ func (n *natsBroker) serve(exit chan bool) error {
|
||||
for _, node := range service.Nodes {
|
||||
u, err := url.Parse("nats://" + node.Address)
|
||||
if err != nil {
|
||||
log.Info(err)
|
||||
if logger.V(logger.InfoLevel, logger.DefaultLogger) {
|
||||
logger.Info(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// append to the cluster routes
|
||||
@@ -242,7 +249,9 @@ func (n *natsBroker) serve(exit chan bool) error {
|
||||
select {
|
||||
case err := <-n.closeCh:
|
||||
if err != nil {
|
||||
log.Info(err)
|
||||
if logger.V(logger.InfoLevel, logger.DefaultLogger) {
|
||||
logger.Info(err)
|
||||
}
|
||||
}
|
||||
case <-exit:
|
||||
// deregister on exit
|
||||
@@ -390,10 +399,30 @@ func (n *natsBroker) Subscribe(topic string, handler Handler, opts ...SubscribeO
|
||||
|
||||
fn := func(msg *nats.Msg) {
|
||||
var m Message
|
||||
if err := n.opts.Codec.Unmarshal(msg.Data, &m); err != nil {
|
||||
pub := &publication{t: msg.Subject}
|
||||
eh := n.opts.ErrorHandler
|
||||
err := n.opts.Codec.Unmarshal(msg.Data, &m)
|
||||
pub.err = err
|
||||
pub.m = &m
|
||||
if err != nil {
|
||||
m.Body = msg.Data
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err)
|
||||
}
|
||||
if eh != nil {
|
||||
eh(pub)
|
||||
}
|
||||
return
|
||||
}
|
||||
handler(&publication{m: &m, t: msg.Subject})
|
||||
if err := handler(pub); err != nil {
|
||||
pub.err = err
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err)
|
||||
}
|
||||
if eh != nil {
|
||||
eh(pub)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sub *nats.Subscription
|
||||
|
@@ -2,6 +2,7 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"sync"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
maddr "github.com/micro/go-micro/v2/util/addr"
|
||||
mnet "github.com/micro/go-micro/v2/util/net"
|
||||
)
|
||||
@@ -23,8 +25,10 @@ type memoryBroker struct {
|
||||
}
|
||||
|
||||
type memoryEvent struct {
|
||||
opts broker.Options
|
||||
topic string
|
||||
message *broker.Message
|
||||
err error
|
||||
message interface{}
|
||||
}
|
||||
|
||||
type memorySubscriber struct {
|
||||
@@ -85,7 +89,7 @@ func (m *memoryBroker) Init(opts ...broker.Option) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryBroker) Publish(topic string, message *broker.Message, opts ...broker.PublishOption) error {
|
||||
func (m *memoryBroker) Publish(topic string, msg *broker.Message, opts ...broker.PublishOption) error {
|
||||
m.RLock()
|
||||
if !m.connected {
|
||||
m.RUnlock()
|
||||
@@ -98,13 +102,30 @@ func (m *memoryBroker) Publish(topic string, message *broker.Message, opts ...br
|
||||
return nil
|
||||
}
|
||||
|
||||
var v interface{}
|
||||
if m.opts.Codec != nil {
|
||||
buf, err := m.opts.Codec.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v = buf
|
||||
} else {
|
||||
v = msg
|
||||
}
|
||||
|
||||
p := &memoryEvent{
|
||||
topic: topic,
|
||||
message: message,
|
||||
message: v,
|
||||
opts: m.opts,
|
||||
}
|
||||
|
||||
for _, sub := range subs {
|
||||
if err := sub.handler(p); err != nil {
|
||||
p.err = err
|
||||
if eh := m.opts.ErrorHandler; eh != nil {
|
||||
eh(p)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -163,13 +184,31 @@ func (m *memoryEvent) Topic() string {
|
||||
}
|
||||
|
||||
func (m *memoryEvent) Message() *broker.Message {
|
||||
return m.message
|
||||
switch v := m.message.(type) {
|
||||
case *broker.Message:
|
||||
return v
|
||||
case []byte:
|
||||
msg := &broker.Message{}
|
||||
if err := m.opts.Codec.Unmarshal(v, msg); err != nil {
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Errorf("[memory]: failed to unmarshal: %v\n", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryEvent) Ack() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryEvent) Error() error {
|
||||
return m.err
|
||||
}
|
||||
|
||||
func (m *memorySubscriber) Options() broker.SubscribeOptions {
|
||||
return m.opts
|
||||
}
|
||||
@@ -184,7 +223,10 @@ func (m *memorySubscriber) Unsubscribe() error {
|
||||
}
|
||||
|
||||
func NewBroker(opts ...broker.Option) broker.Broker {
|
||||
var options broker.Options
|
||||
options := broker.Options{
|
||||
Context: context.Background(),
|
||||
}
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
|
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/codec/json"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/util/addr"
|
||||
"github.com/nats-io/nats-server/v2/server"
|
||||
@@ -50,8 +50,9 @@ type subscriber struct {
|
||||
}
|
||||
|
||||
type publication struct {
|
||||
t string
|
||||
m *broker.Message
|
||||
t string
|
||||
err error
|
||||
m *broker.Message
|
||||
}
|
||||
|
||||
func (p *publication) Topic() string {
|
||||
@@ -67,6 +68,10 @@ func (p *publication) Ack() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *publication) Error() error {
|
||||
return p.err
|
||||
}
|
||||
|
||||
func (s *subscriber) Options() broker.SubscribeOptions {
|
||||
return s.opts
|
||||
}
|
||||
@@ -164,7 +169,9 @@ func (n *natsBroker) serve(exit chan bool) error {
|
||||
for _, node := range service.Nodes {
|
||||
u, err := url.Parse("nats://" + node.Address)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// append to the cluster routes
|
||||
@@ -375,10 +382,30 @@ func (n *natsBroker) Subscribe(topic string, handler broker.Handler, opts ...bro
|
||||
|
||||
fn := func(msg *nats.Msg) {
|
||||
var m broker.Message
|
||||
if err := n.opts.Codec.Unmarshal(msg.Data, &m); err != nil {
|
||||
pub := &publication{t: msg.Subject}
|
||||
eh := n.opts.ErrorHandler
|
||||
err := n.opts.Codec.Unmarshal(msg.Data, &m)
|
||||
pub.err = err
|
||||
pub.m = &m
|
||||
if err != nil {
|
||||
m.Body = msg.Data
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err)
|
||||
}
|
||||
if eh != nil {
|
||||
eh(pub)
|
||||
}
|
||||
return
|
||||
}
|
||||
handler(&publication{m: &m, t: msg.Subject})
|
||||
if err := handler(pub); err != nil {
|
||||
pub.err = err
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error(err)
|
||||
}
|
||||
if eh != nil {
|
||||
eh(pub)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sub *nats.Subscription
|
||||
|
@@ -9,9 +9,14 @@ import (
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Addrs []string
|
||||
Secure bool
|
||||
Codec codec.Marshaler
|
||||
Addrs []string
|
||||
Secure bool
|
||||
Codec codec.Marshaler
|
||||
|
||||
// Handler executed when error happens in broker mesage
|
||||
// processing
|
||||
ErrorHandler Handler
|
||||
|
||||
TLSConfig *tls.Config
|
||||
// Registry used for clustering
|
||||
Registry registry.Registry
|
||||
@@ -81,6 +86,14 @@ func DisableAutoAck() SubscribeOption {
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorHandler will catch all broker errors that cant be handled
|
||||
// in normal way, for example Codec errors
|
||||
func ErrorHandler(h Handler) Option {
|
||||
return func(o *Options) {
|
||||
o.ErrorHandler = h
|
||||
}
|
||||
}
|
||||
|
||||
// Queue sets the name of the queue to share messages on
|
||||
func Queue(name string) SubscribeOption {
|
||||
return func(o *SubscribeOptions) {
|
||||
|
@@ -1,11 +1,15 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: micro/go-micro/broker/service/proto/broker.proto
|
||||
// source: broker/service/proto/broker.proto
|
||||
|
||||
package go_micro_broker
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
@@ -30,7 +34,7 @@ func (m *Empty) Reset() { *m = Empty{} }
|
||||
func (m *Empty) String() string { return proto.CompactTextString(m) }
|
||||
func (*Empty) ProtoMessage() {}
|
||||
func (*Empty) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_178fdc60944ff5e5, []int{0}
|
||||
return fileDescriptor_df4d8f04292cf3fe, []int{0}
|
||||
}
|
||||
|
||||
func (m *Empty) XXX_Unmarshal(b []byte) error {
|
||||
@@ -63,7 +67,7 @@ func (m *PublishRequest) Reset() { *m = PublishRequest{} }
|
||||
func (m *PublishRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PublishRequest) ProtoMessage() {}
|
||||
func (*PublishRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_178fdc60944ff5e5, []int{1}
|
||||
return fileDescriptor_df4d8f04292cf3fe, []int{1}
|
||||
}
|
||||
|
||||
func (m *PublishRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -110,7 +114,7 @@ func (m *SubscribeRequest) Reset() { *m = SubscribeRequest{} }
|
||||
func (m *SubscribeRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SubscribeRequest) ProtoMessage() {}
|
||||
func (*SubscribeRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_178fdc60944ff5e5, []int{2}
|
||||
return fileDescriptor_df4d8f04292cf3fe, []int{2}
|
||||
}
|
||||
|
||||
func (m *SubscribeRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -157,7 +161,7 @@ func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
func (*Message) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_178fdc60944ff5e5, []int{3}
|
||||
return fileDescriptor_df4d8f04292cf3fe, []int{3}
|
||||
}
|
||||
|
||||
func (m *Message) XXX_Unmarshal(b []byte) error {
|
||||
@@ -200,30 +204,171 @@ func init() {
|
||||
proto.RegisterMapType((map[string]string)(nil), "go.micro.broker.Message.HeaderEntry")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("micro/go-micro/broker/service/proto/broker.proto", fileDescriptor_178fdc60944ff5e5)
|
||||
func init() { proto.RegisterFile("broker/service/proto/broker.proto", fileDescriptor_df4d8f04292cf3fe) }
|
||||
|
||||
var fileDescriptor_df4d8f04292cf3fe = []byte{
|
||||
// 299 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x51, 0x4d, 0x4b, 0xc3, 0x40,
|
||||
0x14, 0xec, 0xb6, 0xb6, 0xa1, 0xaf, 0xa2, 0x65, 0x29, 0x12, 0x7a, 0x31, 0x0d, 0x1e, 0x72, 0xda,
|
||||
0x48, 0xbc, 0xa8, 0x88, 0x07, 0xb1, 0xe0, 0x41, 0x41, 0xd6, 0x9b, 0xb7, 0x6c, 0xfa, 0x68, 0x43,
|
||||
0x1b, 0x37, 0xdd, 0x4d, 0x0a, 0xf9, 0x23, 0x9e, 0xfc, 0xb1, 0xd2, 0xdd, 0xf8, 0xd5, 0x50, 0x6f,
|
||||
0x6f, 0xde, 0xce, 0xce, 0x1b, 0x66, 0x60, 0x22, 0x94, 0x5c, 0xa2, 0x0a, 0x35, 0xaa, 0x4d, 0x9a,
|
||||
0x60, 0x98, 0x2b, 0x59, 0xc8, 0xd0, 0x2e, 0x99, 0x01, 0xf4, 0x78, 0x2e, 0x59, 0x96, 0x26, 0x4a,
|
||||
0x32, 0xbb, 0xf6, 0x1d, 0xe8, 0x4e, 0xb3, 0xbc, 0xa8, 0xfc, 0x57, 0x38, 0x7a, 0x2e, 0xc5, 0x2a,
|
||||
0xd5, 0x0b, 0x8e, 0xeb, 0x12, 0x75, 0x41, 0x47, 0xd0, 0x2d, 0x64, 0x9e, 0x26, 0x2e, 0xf1, 0x48,
|
||||
0xd0, 0xe7, 0x16, 0xd0, 0x08, 0x9c, 0x0c, 0xb5, 0x8e, 0xe7, 0xe8, 0xb6, 0x3d, 0x12, 0x0c, 0x22,
|
||||
0x97, 0xed, 0x68, 0xb2, 0x27, 0xfb, 0xce, 0xbf, 0x88, 0xfe, 0x2d, 0x0c, 0x5f, 0x4a, 0xa1, 0x13,
|
||||
0x95, 0x0a, 0xfc, 0x5f, 0x7d, 0x04, 0xdd, 0x75, 0x89, 0xa5, 0xd5, 0xee, 0x73, 0x0b, 0xfc, 0x77,
|
||||
0x02, 0x4e, 0x2d, 0x4a, 0x6f, 0xa0, 0xb7, 0xc0, 0x78, 0x86, 0xca, 0x25, 0x5e, 0x27, 0x18, 0x44,
|
||||
0x67, 0xfb, 0xce, 0xb3, 0x07, 0x43, 0x9b, 0xbe, 0x15, 0xaa, 0xe2, 0xf5, 0x1f, 0x4a, 0xe1, 0x40,
|
||||
0xc8, 0x59, 0x65, 0xe4, 0x0f, 0xb9, 0x99, 0xc7, 0x57, 0x30, 0xf8, 0x45, 0xa5, 0x43, 0xe8, 0x2c,
|
||||
0xb1, 0xaa, 0x6d, 0x6d, 0xc7, 0xad, 0xa9, 0x4d, 0xbc, 0xfa, 0x31, 0x65, 0xc0, 0x75, 0xfb, 0x92,
|
||||
0x44, 0x1f, 0x04, 0x7a, 0x77, 0xe6, 0x2a, 0xbd, 0x07, 0xa7, 0xce, 0x8f, 0x9e, 0x36, 0x2c, 0xfd,
|
||||
0x4d, 0x76, 0x7c, 0xd2, 0x20, 0xd8, 0x0e, 0x5a, 0xf4, 0x11, 0xfa, 0xdf, 0x49, 0xd1, 0x49, 0x83,
|
||||
0xb6, 0x9b, 0xe2, 0x78, 0x6f, 0xf8, 0x7e, 0xeb, 0x9c, 0x88, 0x9e, 0x29, 0xfd, 0xe2, 0x33, 0x00,
|
||||
0x00, 0xff, 0xff, 0x19, 0x9f, 0x10, 0x75, 0x19, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
var fileDescriptor_178fdc60944ff5e5 = []byte{
|
||||
// 305 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x51, 0x4d, 0x4f, 0xc2, 0x40,
|
||||
0x14, 0x64, 0x41, 0x68, 0x78, 0x18, 0x25, 0x1b, 0x62, 0x1a, 0x2e, 0x62, 0xe3, 0x81, 0x8b, 0x5b,
|
||||
0x52, 0x2f, 0x6a, 0x8c, 0x07, 0x23, 0x89, 0x07, 0x4d, 0xcc, 0x7a, 0xf3, 0xd6, 0x2d, 0x2f, 0xa5,
|
||||
0x81, 0xba, 0x65, 0xb7, 0x25, 0xe9, 0x1f, 0xf1, 0xe4, 0x8f, 0x35, 0xec, 0x16, 0x3f, 0x68, 0xf0,
|
||||
0x36, 0xf3, 0x76, 0x76, 0xde, 0x64, 0x1e, 0x4c, 0xd2, 0x24, 0x52, 0xd2, 0x8f, 0xe5, 0x85, 0x05,
|
||||
0x42, 0xc9, 0x05, 0x2a, 0x5f, 0xa3, 0x5a, 0x27, 0x11, 0xfa, 0x99, 0x92, 0xf9, 0x76, 0xc8, 0x0c,
|
||||
0xa1, 0xc7, 0xb1, 0x64, 0x46, 0xcb, 0xec, 0xd8, 0x73, 0xa0, 0x3d, 0x4d, 0xb3, 0xbc, 0xf4, 0xde,
|
||||
0xe0, 0xe8, 0xa5, 0x10, 0xcb, 0x44, 0xcf, 0x39, 0xae, 0x0a, 0xd4, 0x39, 0x1d, 0x40, 0x3b, 0x97,
|
||||
0x59, 0x12, 0xb9, 0x64, 0x44, 0xc6, 0x5d, 0x6e, 0x09, 0x0d, 0xc0, 0x49, 0x51, 0xeb, 0x30, 0x46,
|
||||
0xb7, 0x39, 0x22, 0xe3, 0x5e, 0xe0, 0xb2, 0x1d, 0x4f, 0xf6, 0x6c, 0xdf, 0xf9, 0x56, 0xe8, 0xdd,
|
||||
0x41, 0xff, 0xb5, 0x10, 0x3a, 0x52, 0x89, 0xc0, 0xff, 0xdd, 0x07, 0xd0, 0x5e, 0x15, 0x58, 0x58,
|
||||
0xef, 0x2e, 0xb7, 0xc4, 0xfb, 0x20, 0xe0, 0x54, 0xa6, 0xf4, 0x16, 0x3a, 0x73, 0x0c, 0x67, 0xa8,
|
||||
0x5c, 0x32, 0x6a, 0x8d, 0x7b, 0xc1, 0xf9, 0xbe, 0xf5, 0xec, 0xd1, 0xc8, 0xa6, 0xef, 0xb9, 0x2a,
|
||||
0x79, 0xf5, 0x87, 0x52, 0x38, 0x10, 0x72, 0x56, 0x1a, 0xfb, 0x43, 0x6e, 0xf0, 0xf0, 0x1a, 0x7a,
|
||||
0xbf, 0xa4, 0xb4, 0x0f, 0xad, 0x05, 0x96, 0x55, 0xac, 0x0d, 0xdc, 0x84, 0x5a, 0x87, 0xcb, 0x9f,
|
||||
0x50, 0x86, 0xdc, 0x34, 0xaf, 0x48, 0xf0, 0x49, 0xa0, 0x73, 0x6f, 0xb6, 0xd2, 0x07, 0x70, 0xaa,
|
||||
0xfe, 0xe8, 0x69, 0x2d, 0xd2, 0xdf, 0x66, 0x87, 0x27, 0x35, 0x81, 0xbd, 0x41, 0x83, 0x3e, 0x41,
|
||||
0xf7, 0xbb, 0x29, 0x7a, 0x56, 0x93, 0xed, 0xb6, 0x38, 0xdc, 0x5b, 0xbe, 0xd7, 0x98, 0x10, 0xd1,
|
||||
0x31, 0x47, 0xbf, 0xfc, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x60, 0x8c, 0x40, 0xd5, 0x28, 0x02, 0x00,
|
||||
0x00,
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// BrokerClient is the client API for Broker service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type BrokerClient interface {
|
||||
Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*Empty, error)
|
||||
Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (Broker_SubscribeClient, error)
|
||||
}
|
||||
|
||||
type brokerClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewBrokerClient(cc *grpc.ClientConn) BrokerClient {
|
||||
return &brokerClient{cc}
|
||||
}
|
||||
|
||||
func (c *brokerClient) Publish(ctx context.Context, in *PublishRequest, opts ...grpc.CallOption) (*Empty, error) {
|
||||
out := new(Empty)
|
||||
err := c.cc.Invoke(ctx, "/go.micro.broker.Broker/Publish", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *brokerClient) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (Broker_SubscribeClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_Broker_serviceDesc.Streams[0], "/go.micro.broker.Broker/Subscribe", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &brokerSubscribeClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Broker_SubscribeClient interface {
|
||||
Recv() (*Message, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type brokerSubscribeClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *brokerSubscribeClient) Recv() (*Message, error) {
|
||||
m := new(Message)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// BrokerServer is the server API for Broker service.
|
||||
type BrokerServer interface {
|
||||
Publish(context.Context, *PublishRequest) (*Empty, error)
|
||||
Subscribe(*SubscribeRequest, Broker_SubscribeServer) error
|
||||
}
|
||||
|
||||
// UnimplementedBrokerServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedBrokerServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedBrokerServer) Publish(ctx context.Context, req *PublishRequest) (*Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Publish not implemented")
|
||||
}
|
||||
func (*UnimplementedBrokerServer) Subscribe(req *SubscribeRequest, srv Broker_SubscribeServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Subscribe not implemented")
|
||||
}
|
||||
|
||||
func RegisterBrokerServer(s *grpc.Server, srv BrokerServer) {
|
||||
s.RegisterService(&_Broker_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Broker_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(PublishRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BrokerServer).Publish(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/go.micro.broker.Broker/Publish",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BrokerServer).Publish(ctx, req.(*PublishRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Broker_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(SubscribeRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(BrokerServer).Subscribe(m, &brokerSubscribeServer{stream})
|
||||
}
|
||||
|
||||
type Broker_SubscribeServer interface {
|
||||
Send(*Message) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type brokerSubscribeServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *brokerSubscribeServer) Send(m *Message) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
var _Broker_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "go.micro.broker.Broker",
|
||||
HandlerType: (*BrokerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Publish",
|
||||
Handler: _Broker_Publish_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Subscribe",
|
||||
Handler: _Broker_Subscribe_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "broker/service/proto/broker.proto",
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: micro/go-micro/broker/service/proto/broker.proto
|
||||
// source: broker/service/proto/broker.proto
|
||||
|
||||
package go_micro_broker
|
||||
|
||||
@@ -44,12 +44,6 @@ type brokerService struct {
|
||||
}
|
||||
|
||||
func NewBrokerService(name string, c client.Client) BrokerService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "go.micro.broker"
|
||||
}
|
||||
return &brokerService{
|
||||
c: c,
|
||||
name: name,
|
||||
@@ -79,6 +73,7 @@ func (c *brokerService) Subscribe(ctx context.Context, in *SubscribeRequest, opt
|
||||
}
|
||||
|
||||
type Broker_SubscribeService interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
Close() error
|
||||
@@ -93,6 +88,10 @@ func (x *brokerServiceSubscribe) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *brokerServiceSubscribe) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *brokerServiceSubscribe) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
@@ -146,6 +145,7 @@ func (h *brokerHandler) Subscribe(ctx context.Context, stream server.Stream) err
|
||||
}
|
||||
|
||||
type Broker_SubscribeStream interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
Close() error
|
||||
@@ -160,6 +160,10 @@ func (x *brokerSubscribeStream) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *brokerSubscribeStream) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *brokerSubscribeStream) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
pb "github.com/micro/go-micro/v2/broker/service/proto"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type serviceBroker struct {
|
||||
@@ -45,7 +45,9 @@ func (b *serviceBroker) Options() broker.Options {
|
||||
}
|
||||
|
||||
func (b *serviceBroker) Publish(topic string, msg *broker.Message, opts ...broker.PublishOption) error {
|
||||
log.Debugf("Publishing to topic %s broker %v", topic, b.Addrs)
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("Publishing to topic %s broker %v", topic, b.Addrs)
|
||||
}
|
||||
_, err := b.Client.Publish(context.TODO(), &pb.PublishRequest{
|
||||
Topic: topic,
|
||||
Message: &pb.Message{
|
||||
@@ -61,7 +63,9 @@ func (b *serviceBroker) Subscribe(topic string, handler broker.Handler, opts ...
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
log.Debugf("Subscribing to topic %s queue %s broker %v", topic, options.Queue, b.Addrs)
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("Subscribing to topic %s queue %s broker %v", topic, options.Queue, b.Addrs)
|
||||
}
|
||||
stream, err := b.Client.Subscribe(context.TODO(), &pb.SubscribeRequest{
|
||||
Topic: topic,
|
||||
Queue: options.Queue,
|
||||
@@ -83,19 +87,27 @@ func (b *serviceBroker) Subscribe(topic string, handler broker.Handler, opts ...
|
||||
for {
|
||||
select {
|
||||
case <-sub.closed:
|
||||
log.Debugf("Unsubscribed from topic %s", topic)
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("Unsubscribed from topic %s", topic)
|
||||
}
|
||||
return
|
||||
default:
|
||||
// run the subscriber
|
||||
log.Debugf("Streaming from broker %v to topic [%s] queue [%s]", b.Addrs, topic, options.Queue)
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
// run the subscriber
|
||||
logger.Debugf("Streaming from broker %v to topic [%s] queue [%s]", b.Addrs, topic, options.Queue)
|
||||
}
|
||||
if err := sub.run(); err != nil {
|
||||
log.Debugf("Resubscribing to topic %s broker %v", topic, b.Addrs)
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("Resubscribing to topic %s broker %v", topic, b.Addrs)
|
||||
}
|
||||
stream, err := b.Client.Subscribe(context.TODO(), &pb.SubscribeRequest{
|
||||
Topic: topic,
|
||||
Queue: options.Queue,
|
||||
}, client.WithAddress(b.Addrs...), client.WithRequestTimeout(time.Hour))
|
||||
if err != nil {
|
||||
log.Debugf("Failed to resubscribe to topic %s: %v", topic, err)
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("Failed to resubscribe to topic %s: %v", topic, err)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ package service
|
||||
import (
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
pb "github.com/micro/go-micro/v2/broker/service/proto"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type serviceSub struct {
|
||||
@@ -17,6 +17,7 @@ type serviceSub struct {
|
||||
|
||||
type serviceEvent struct {
|
||||
topic string
|
||||
err error
|
||||
message *broker.Message
|
||||
}
|
||||
|
||||
@@ -32,6 +33,10 @@ func (s *serviceEvent) Ack() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *serviceEvent) Error() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
func (s *serviceSub) isClosed() bool {
|
||||
select {
|
||||
case <-s.closed:
|
||||
@@ -57,7 +62,9 @@ func (s *serviceSub) run() error {
|
||||
// TODO: do not fail silently
|
||||
msg, err := s.stream.Recv()
|
||||
if err != nil {
|
||||
log.Debugf("Streaming error for subcription to topic %s: %v", s.Topic(), err)
|
||||
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
|
||||
logger.Debugf("Streaming error for subcription to topic %s: %v", s.Topic(), err)
|
||||
}
|
||||
|
||||
// close the exit channel
|
||||
close(exit)
|
||||
@@ -71,14 +78,14 @@ func (s *serviceSub) run() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: handle error
|
||||
s.handler(&serviceEvent{
|
||||
p := &serviceEvent{
|
||||
topic: s.topic,
|
||||
message: &broker.Message{
|
||||
Header: msg.Header,
|
||||
Body: msg.Body,
|
||||
},
|
||||
})
|
||||
}
|
||||
p.err = s.handler(p)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -8,7 +9,6 @@ import (
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/codec/bytes"
|
||||
"google.golang.org/grpc"
|
||||
@@ -21,6 +21,7 @@ type bytesCodec struct{}
|
||||
type wrapCodec struct{ encoding.Codec }
|
||||
|
||||
var jsonpbMarshaler = &jsonpb.Marshaler{}
|
||||
var useNumber bool
|
||||
|
||||
var (
|
||||
defaultGRPCCodecs = map[string]encoding.Codec{
|
||||
@@ -33,18 +34,11 @@ var (
|
||||
"application/grpc+proto": protoCodec{},
|
||||
"application/grpc+bytes": bytesCodec{},
|
||||
}
|
||||
|
||||
json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
)
|
||||
|
||||
// UseNumber fix unmarshal Number(8234567890123456789) to interface(8.234567890123457e+18)
|
||||
func UseNumber() {
|
||||
json = jsoniter.Config{
|
||||
UseNumber: true,
|
||||
EscapeHTML: true,
|
||||
SortMapKeys: true,
|
||||
ValidateJsonRawMessage: true,
|
||||
}.Froze()
|
||||
useNumber = true
|
||||
}
|
||||
|
||||
func (w wrapCodec) String() string {
|
||||
@@ -117,7 +111,9 @@ func (jsonCodec) Marshal(v interface{}) ([]byte, error) {
|
||||
|
||||
return []byte(s), err
|
||||
}
|
||||
|
||||
if b, ok := v.(*bytes.Frame); ok {
|
||||
return b.Data, nil
|
||||
}
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
@@ -125,10 +121,19 @@ func (jsonCodec) Unmarshal(data []byte, v interface{}) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
if b, ok := v.(*bytes.Frame); ok {
|
||||
b.Data = data
|
||||
return nil
|
||||
}
|
||||
if pb, ok := v.(proto.Message); ok {
|
||||
return jsonpb.Unmarshal(b.NewReader(data), pb)
|
||||
}
|
||||
return json.Unmarshal(data, v)
|
||||
|
||||
dec := json.NewDecoder(b.NewReader(data))
|
||||
if useNumber {
|
||||
dec.UseNumber()
|
||||
}
|
||||
return dec.Decode(v)
|
||||
}
|
||||
|
||||
func (jsonCodec) Name() string {
|
||||
|
@@ -17,18 +17,21 @@ func microError(err error) error {
|
||||
}
|
||||
|
||||
// grpc error
|
||||
if s, ok := status.FromError(err); ok {
|
||||
details := s.Details()
|
||||
if len(details) == 0 {
|
||||
if e := errors.Parse(s.Message()); e.Code > 0 {
|
||||
return e // actually a micro error
|
||||
}
|
||||
return errors.InternalServerError("go.micro.client", s.Message())
|
||||
}
|
||||
// return first error from details
|
||||
return details[0].(error)
|
||||
s, ok := status.FromError(err)
|
||||
if !ok {
|
||||
return err
|
||||
}
|
||||
|
||||
// do nothing
|
||||
return err
|
||||
// return first error from details
|
||||
if details := s.Details(); len(details) > 0 {
|
||||
return microError(details[0].(error))
|
||||
}
|
||||
|
||||
// try to decode micro *errors.Error
|
||||
if e := errors.Parse(s.Message()); e.Code > 0 {
|
||||
return e // actually a micro error
|
||||
}
|
||||
|
||||
// fallback
|
||||
return errors.InternalServerError("go.micro.client", s.Message())
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
@@ -119,7 +120,7 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R
|
||||
if md, ok := metadata.FromContext(ctx); ok {
|
||||
header = make(map[string]string, len(md))
|
||||
for k, v := range md {
|
||||
header[k] = v
|
||||
header[strings.ToLower(k)] = v
|
||||
}
|
||||
} else {
|
||||
header = make(map[string]string)
|
||||
@@ -129,9 +130,12 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R
|
||||
header["timeout"] = fmt.Sprintf("%d", opts.RequestTimeout)
|
||||
// set the content type for the request
|
||||
header["x-content-type"] = req.ContentType()
|
||||
|
||||
// set the authorization token if one is saved locally
|
||||
if token, err := config.Get("token"); err == nil && len(token) > 0 {
|
||||
header["authorization"] = fmt.Sprintf("Bearer %v", token)
|
||||
if len(header["authorization"]) == 0 {
|
||||
if token, err := config.Get("token"); err == nil && len(token) > 0 {
|
||||
header["authorization"] = auth.BearerScheme + token
|
||||
}
|
||||
}
|
||||
|
||||
md := gmetadata.New(header)
|
||||
@@ -388,6 +392,11 @@ func (g *grpcClient) NewRequest(service, method string, req interface{}, reqOpts
|
||||
}
|
||||
|
||||
func (g *grpcClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
if req == nil {
|
||||
return errors.InternalServerError("go.micro.client", "req is nil")
|
||||
} else if rsp == nil {
|
||||
return errors.InternalServerError("go.micro.client", "rsp is nil")
|
||||
}
|
||||
// make a copy of call opts
|
||||
callOpts := g.opts.CallOptions
|
||||
for _, opt := range opts {
|
||||
@@ -454,6 +463,10 @@ func (g *grpcClient) Call(ctx context.Context, req client.Request, rsp interface
|
||||
// make the call
|
||||
err = gcall(ctx, node, req, rsp, callOpts)
|
||||
g.opts.Selector.Mark(service, node, err)
|
||||
if verr, ok := err.(*errors.Error); ok {
|
||||
return verr
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
)
|
||||
|
||||
type pool struct {
|
||||
@@ -77,6 +78,32 @@ func (p *pool) getConn(addr string, opts ...grpc.DialOption) (*poolConn, error)
|
||||
// otherwise we'll create a new conn
|
||||
conn := sp.head.next
|
||||
for conn != nil {
|
||||
// check conn state
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md
|
||||
switch conn.GetState() {
|
||||
case connectivity.Connecting:
|
||||
conn = conn.next
|
||||
continue
|
||||
case connectivity.Shutdown:
|
||||
next := conn.next
|
||||
if conn.streams == 0 {
|
||||
removeConn(conn)
|
||||
sp.idle--
|
||||
}
|
||||
conn = next
|
||||
continue
|
||||
case connectivity.TransientFailure:
|
||||
next := conn.next
|
||||
if conn.streams == 0 {
|
||||
removeConn(conn)
|
||||
conn.ClientConn.Close()
|
||||
sp.idle--
|
||||
}
|
||||
conn = next
|
||||
continue
|
||||
case connectivity.Ready:
|
||||
case connectivity.Idle:
|
||||
}
|
||||
// a old conn
|
||||
if now-conn.created > p.ttl {
|
||||
next := conn.next
|
||||
|
@@ -1,11 +1,15 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/v2/client/proto/client.proto
|
||||
// source: client/service/proto/client.proto
|
||||
|
||||
package go_micro_client
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
@@ -34,7 +38,7 @@ func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d418333f021a3308, []int{0}
|
||||
return fileDescriptor_27c3d425ddd1a066, []int{0}
|
||||
}
|
||||
|
||||
func (m *Request) XXX_Unmarshal(b []byte) error {
|
||||
@@ -94,7 +98,7 @@ func (m *Response) Reset() { *m = Response{} }
|
||||
func (m *Response) String() string { return proto.CompactTextString(m) }
|
||||
func (*Response) ProtoMessage() {}
|
||||
func (*Response) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d418333f021a3308, []int{1}
|
||||
return fileDescriptor_27c3d425ddd1a066, []int{1}
|
||||
}
|
||||
|
||||
func (m *Response) XXX_Unmarshal(b []byte) error {
|
||||
@@ -135,7 +139,7 @@ func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
func (*Message) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d418333f021a3308, []int{2}
|
||||
return fileDescriptor_27c3d425ddd1a066, []int{2}
|
||||
}
|
||||
|
||||
func (m *Message) XXX_Unmarshal(b []byte) error {
|
||||
@@ -183,28 +187,216 @@ func init() {
|
||||
proto.RegisterType((*Message)(nil), "go.micro.client.Message")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/go-micro/v2/client/proto/client.proto", fileDescriptor_d418333f021a3308)
|
||||
func init() { proto.RegisterFile("client/service/proto/client.proto", fileDescriptor_27c3d425ddd1a066) }
|
||||
|
||||
var fileDescriptor_27c3d425ddd1a066 = []byte{
|
||||
// 267 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0xc1, 0x4b, 0xc3, 0x30,
|
||||
0x14, 0xc6, 0x97, 0x6d, 0xb6, 0xf3, 0x39, 0x10, 0x1e, 0x1e, 0x62, 0x0f, 0xb2, 0xf5, 0xd4, 0x53,
|
||||
0x2b, 0x7a, 0x16, 0x0f, 0x3d, 0x0b, 0x52, 0xc5, 0xab, 0xb4, 0xd9, 0x63, 0x06, 0xba, 0x24, 0x36,
|
||||
0xd9, 0xa0, 0x7f, 0xa4, 0xff, 0x93, 0x90, 0x46, 0x27, 0xba, 0x5d, 0xbc, 0xe5, 0xfb, 0x7e, 0xe4,
|
||||
0x7b, 0x2f, 0x5f, 0x60, 0x29, 0x5a, 0x49, 0xca, 0x15, 0x96, 0xba, 0x9d, 0x14, 0x54, 0x98, 0x4e,
|
||||
0x3b, 0x5d, 0x0c, 0x66, 0xee, 0x05, 0x9e, 0xaf, 0x75, 0xbe, 0x91, 0xa2, 0xd3, 0xf9, 0x60, 0xa7,
|
||||
0x3b, 0x88, 0x2b, 0x7a, 0xdf, 0x92, 0x75, 0xc8, 0x21, 0x0e, 0x37, 0x39, 0x5b, 0xb0, 0xec, 0xb4,
|
||||
0xfa, 0x92, 0x98, 0xc0, 0x8c, 0xd4, 0xca, 0x68, 0xa9, 0x1c, 0x1f, 0x7b, 0xf4, 0xad, 0x71, 0x09,
|
||||
0x73, 0xa1, 0x95, 0x23, 0xe5, 0x5e, 0x5d, 0x6f, 0x88, 0x4f, 0x3c, 0x3f, 0x0b, 0xde, 0x73, 0x6f,
|
||||
0x08, 0x11, 0xa6, 0x8d, 0x5e, 0xf5, 0x7c, 0xba, 0x60, 0xd9, 0xbc, 0xf2, 0xe7, 0xf4, 0x0a, 0x66,
|
||||
0x15, 0x59, 0xa3, 0x95, 0xdd, 0x73, 0xf6, 0x83, 0xbf, 0x40, 0xfc, 0x40, 0xd6, 0xd6, 0x6b, 0xc2,
|
||||
0x0b, 0x38, 0x71, 0xda, 0x48, 0x11, 0xb6, 0x1a, 0xc4, 0x9f, 0xb9, 0xe3, 0xe3, 0x73, 0x27, 0xfb,
|
||||
0xdc, 0x9b, 0x0f, 0x06, 0x51, 0xe9, 0x9f, 0x8e, 0x77, 0x30, 0x2d, 0xeb, 0xb6, 0x45, 0x9e, 0xff,
|
||||
0x2a, 0x25, 0x0f, 0x8d, 0x24, 0x97, 0x07, 0xc8, 0xb0, 0x73, 0x3a, 0xc2, 0x12, 0xa2, 0x27, 0xd7,
|
||||
0x51, 0xbd, 0xf9, 0x67, 0x40, 0xc6, 0xae, 0x19, 0xde, 0x43, 0xfc, 0xb8, 0x6d, 0x5a, 0x69, 0xdf,
|
||||
0x0e, 0xa4, 0x84, 0x02, 0x92, 0xa3, 0x24, 0x1d, 0x35, 0x91, 0xff, 0xd7, 0xdb, 0xcf, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xd6, 0x3f, 0xc3, 0xa1, 0xfc, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
var fileDescriptor_d418333f021a3308 = []byte{
|
||||
// 279 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0x31, 0x4f, 0xfb, 0x30,
|
||||
0x10, 0xc5, 0xeb, 0xb6, 0xff, 0xa4, 0xff, 0xa3, 0x12, 0x92, 0xc5, 0x60, 0x32, 0xa0, 0x92, 0x29,
|
||||
0x0b, 0x0e, 0xa2, 0x33, 0x62, 0xc8, 0x8c, 0x84, 0x02, 0x62, 0x45, 0x89, 0x7b, 0x4a, 0x2d, 0x25,
|
||||
0xb6, 0x89, 0x9d, 0x4a, 0xf9, 0x90, 0x7c, 0x27, 0x24, 0x27, 0xa5, 0x08, 0xda, 0x85, 0xed, 0xde,
|
||||
0xfd, 0xac, 0x77, 0xe7, 0x77, 0xb0, 0xae, 0xa4, 0xdb, 0x76, 0x25, 0x17, 0xba, 0x49, 0x1b, 0x29,
|
||||
0x5a, 0x9d, 0x56, 0xfa, 0x66, 0x28, 0x44, 0x2d, 0x51, 0xb9, 0xd4, 0xb4, 0xda, 0xed, 0x05, 0xf7,
|
||||
0x82, 0x9e, 0x57, 0x9a, 0xfb, 0x37, 0x7c, 0x68, 0xc7, 0x3b, 0x08, 0x73, 0x7c, 0xef, 0xd0, 0x3a,
|
||||
0xca, 0x20, 0xb4, 0xd8, 0xee, 0xa4, 0x40, 0x46, 0x56, 0x24, 0xf9, 0x9f, 0xef, 0x25, 0x8d, 0x60,
|
||||
0x81, 0x6a, 0x63, 0xb4, 0x54, 0x8e, 0x4d, 0x3d, 0xfa, 0xd2, 0xf4, 0x1a, 0x96, 0x42, 0x2b, 0x87,
|
||||
0xca, 0xbd, 0xb9, 0xde, 0x20, 0x9b, 0x79, 0x7e, 0x36, 0xf6, 0x5e, 0x7a, 0x83, 0x94, 0xc2, 0xbc,
|
||||
0xd4, 0x9b, 0x9e, 0xcd, 0x57, 0x24, 0x59, 0xe6, 0xbe, 0x8e, 0xaf, 0x60, 0x91, 0xa3, 0x35, 0x5a,
|
||||
0xd9, 0x03, 0x27, 0xdf, 0xf8, 0x2b, 0x84, 0x8f, 0x68, 0x6d, 0x51, 0x21, 0xbd, 0x80, 0x7f, 0x4e,
|
||||
0x1b, 0x29, 0xc6, 0xad, 0x06, 0xf1, 0x6b, 0xee, 0xf4, 0xf4, 0xdc, 0xd9, 0xc1, 0xf7, 0xee, 0x83,
|
||||
0x40, 0x90, 0xf9, 0xaf, 0xd3, 0x7b, 0x98, 0x67, 0x45, 0x5d, 0x53, 0xc6, 0x7f, 0x84, 0xc2, 0xc7,
|
||||
0x44, 0xa2, 0xcb, 0x23, 0x64, 0xd8, 0x39, 0x9e, 0xd0, 0x0c, 0x82, 0x67, 0xd7, 0x62, 0xd1, 0xfc,
|
||||
0xd1, 0x20, 0x21, 0xb7, 0x84, 0x3e, 0x40, 0xf8, 0xd4, 0x95, 0xb5, 0xb4, 0xdb, 0x23, 0x2e, 0x63,
|
||||
0x00, 0xd1, 0x49, 0x12, 0x4f, 0xca, 0xc0, 0xdf, 0x75, 0xfd, 0x19, 0x00, 0x00, 0xff, 0xff, 0xb6,
|
||||
0x4d, 0x6e, 0xd5, 0x0e, 0x02, 0x00, 0x00,
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// 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 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) (Client_StreamClient, error)
|
||||
// Publish publishes a message and returns an empty Message
|
||||
Publish(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error)
|
||||
}
|
||||
|
||||
type clientClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewClientClient(cc *grpc.ClientConn) ClientClient {
|
||||
return &clientClient{cc}
|
||||
}
|
||||
|
||||
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.Client/Call", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
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 := &clientStreamClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Client_StreamClient interface {
|
||||
Send(*Request) error
|
||||
Recv() (*Response, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type clientStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *clientStreamClient) Send(m *Request) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *clientStreamClient) Recv() (*Response, error) {
|
||||
m := new(Response)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
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.Client/Publish", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// 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(Client_StreamServer) error
|
||||
// Publish publishes a message and returns an empty Message
|
||||
Publish(context.Context, *Message) (*Message, error)
|
||||
}
|
||||
|
||||
// UnimplementedClientServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedClientServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedClientServer) Call(ctx context.Context, req *Request) (*Response, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Call not implemented")
|
||||
}
|
||||
func (*UnimplementedClientServer) Stream(srv Client_StreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Stream not implemented")
|
||||
}
|
||||
func (*UnimplementedClientServer) Publish(ctx context.Context, req *Message) (*Message, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Publish not implemented")
|
||||
}
|
||||
|
||||
func RegisterClientServer(s *grpc.Server, srv ClientServer) {
|
||||
s.RegisterService(&_Client_serviceDesc, srv)
|
||||
}
|
||||
|
||||
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.(ClientServer).Call(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/go.micro.client.Client/Call",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ClientServer).Call(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Client_Stream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(ClientServer).Stream(&clientStreamServer{stream})
|
||||
}
|
||||
|
||||
type Client_StreamServer interface {
|
||||
Send(*Response) error
|
||||
Recv() (*Request, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type clientStreamServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *clientStreamServer) Send(m *Response) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *clientStreamServer) Recv() (*Request, error) {
|
||||
m := new(Request)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
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.(ClientServer).Publish(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/go.micro.client.Client/Publish",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ClientServer).Publish(ctx, req.(*Message))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Client_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "go.micro.client.Client",
|
||||
HandlerType: (*ClientServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Call",
|
||||
Handler: _Client_Call_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Publish",
|
||||
Handler: _Client_Publish_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Stream",
|
||||
Handler: _Client_Stream_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "client/service/proto/client.proto",
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/v2/client/proto/client.proto
|
||||
// source: client/service/proto/client.proto
|
||||
|
||||
package go_micro_client
|
||||
|
||||
@@ -48,12 +48,6 @@ type clientService struct {
|
||||
}
|
||||
|
||||
func NewClientService(name string, c client.Client) ClientService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "go.micro.client"
|
||||
}
|
||||
return &clientService{
|
||||
c: c,
|
||||
name: name,
|
||||
@@ -80,6 +74,7 @@ func (c *clientService) Stream(ctx context.Context, opts ...client.CallOption) (
|
||||
}
|
||||
|
||||
type Client_StreamService interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
Close() error
|
||||
@@ -95,6 +90,10 @@ func (x *clientServiceStream) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *clientServiceStream) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *clientServiceStream) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
@@ -163,6 +162,7 @@ func (h *clientHandler) Stream(ctx context.Context, stream server.Stream) error
|
||||
}
|
||||
|
||||
type Client_StreamStream interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
Close() error
|
||||
@@ -178,6 +178,10 @@ func (x *clientStreamStream) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *clientStreamStream) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *clientStreamStream) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
|
@@ -1,83 +1,144 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: envelope.proto
|
||||
// DO NOT EDIT!
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: codec/protorpc/envelope.proto
|
||||
|
||||
/*
|
||||
Package proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
envelope.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Response
|
||||
*/
|
||||
package protorpc
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import json "encoding/json"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference proto, json, and math imports to suppress error if they are not otherwise used.
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = &json.SyntaxError{}
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Request struct {
|
||||
ServiceMethod *string `protobuf:"bytes,1,opt,name=service_method" json:"service_method,omitempty"`
|
||||
Seq *uint64 `protobuf:"fixed64,2,opt,name=seq" json:"seq,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
ServiceMethod string `protobuf:"bytes,1,opt,name=service_method,json=serviceMethod,proto3" json:"service_method,omitempty"`
|
||||
Seq uint64 `protobuf:"fixed64,2,opt,name=seq,proto3" json:"seq,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_12fd17ed7ee86a33, []int{0}
|
||||
}
|
||||
|
||||
func (m *Request) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Request.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Request) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Request.Merge(m, src)
|
||||
}
|
||||
func (m *Request) XXX_Size() int {
|
||||
return xxx_messageInfo_Request.Size(m)
|
||||
}
|
||||
func (m *Request) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Request.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Request proto.InternalMessageInfo
|
||||
|
||||
func (m *Request) GetServiceMethod() string {
|
||||
if m != nil && m.ServiceMethod != nil {
|
||||
return *m.ServiceMethod
|
||||
if m != nil {
|
||||
return m.ServiceMethod
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Request) GetSeq() uint64 {
|
||||
if m != nil && m.Seq != nil {
|
||||
return *m.Seq
|
||||
if m != nil {
|
||||
return m.Seq
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
ServiceMethod *string `protobuf:"bytes,1,opt,name=service_method" json:"service_method,omitempty"`
|
||||
Seq *uint64 `protobuf:"fixed64,2,opt,name=seq" json:"seq,omitempty"`
|
||||
Error *string `protobuf:"bytes,3,opt,name=error" json:"error,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
ServiceMethod string `protobuf:"bytes,1,opt,name=service_method,json=serviceMethod,proto3" json:"service_method,omitempty"`
|
||||
Seq uint64 `protobuf:"fixed64,2,opt,name=seq,proto3" json:"seq,omitempty"`
|
||||
Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Response) Reset() { *m = Response{} }
|
||||
func (m *Response) String() string { return proto.CompactTextString(m) }
|
||||
func (*Response) ProtoMessage() {}
|
||||
func (*Response) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_12fd17ed7ee86a33, []int{1}
|
||||
}
|
||||
|
||||
func (m *Response) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Response.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Response) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Response.Merge(m, src)
|
||||
}
|
||||
func (m *Response) XXX_Size() int {
|
||||
return xxx_messageInfo_Response.Size(m)
|
||||
}
|
||||
func (m *Response) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Response.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Response proto.InternalMessageInfo
|
||||
|
||||
func (m *Response) GetServiceMethod() string {
|
||||
if m != nil && m.ServiceMethod != nil {
|
||||
return *m.ServiceMethod
|
||||
if m != nil {
|
||||
return m.ServiceMethod
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Response) GetSeq() uint64 {
|
||||
if m != nil && m.Seq != nil {
|
||||
return *m.Seq
|
||||
if m != nil {
|
||||
return m.Seq
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Response) GetError() string {
|
||||
if m != nil && m.Error != nil {
|
||||
return *m.Error
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "protorpc.Request")
|
||||
proto.RegisterType((*Response)(nil), "protorpc.Response")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("codec/protorpc/envelope.proto", fileDescriptor_12fd17ed7ee86a33) }
|
||||
|
||||
var fileDescriptor_12fd17ed7ee86a33 = []byte{
|
||||
// 148 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4d, 0xce, 0x4f, 0x49,
|
||||
0x4d, 0xd6, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x2f, 0x2a, 0x48, 0xd6, 0x4f, 0xcd, 0x2b, 0x4b, 0xcd,
|
||||
0xc9, 0x2f, 0x48, 0xd5, 0x03, 0x8b, 0x08, 0x71, 0xc0, 0x24, 0x94, 0x9c, 0xb8, 0xd8, 0x83, 0x52,
|
||||
0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0x54, 0xb9, 0xf8, 0x8a, 0x53, 0x8b, 0xca, 0x32, 0x93, 0x53,
|
||||
0xe3, 0x73, 0x53, 0x4b, 0x32, 0xf2, 0x53, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x78, 0xa1,
|
||||
0xa2, 0xbe, 0x60, 0x41, 0x21, 0x01, 0x2e, 0xe6, 0xe2, 0xd4, 0x42, 0x09, 0x26, 0x05, 0x46, 0x0d,
|
||||
0xb6, 0x20, 0x10, 0x53, 0x29, 0x92, 0x8b, 0x23, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x95,
|
||||
0x6c, 0x43, 0x84, 0x44, 0xb8, 0x58, 0x53, 0x8b, 0x8a, 0xf2, 0x8b, 0x24, 0x98, 0xc1, 0xea, 0x21,
|
||||
0x9c, 0x24, 0x36, 0xb0, 0x43, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe4, 0x73, 0x3a, 0x4b,
|
||||
0xd0, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
21
codec/protorpc/envelope.pb.micro.go
Normal file
21
codec/protorpc/envelope.pb.micro.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: codec/protorpc/envelope.proto
|
||||
|
||||
package protorpc
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
@@ -1,12 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package protorpc;
|
||||
|
||||
message Request {
|
||||
optional string service_method = 1;
|
||||
optional fixed64 seq = 2;
|
||||
string service_method = 1;
|
||||
fixed64 seq = 2;
|
||||
}
|
||||
|
||||
message Response {
|
||||
optional string service_method = 1;
|
||||
optional fixed64 seq = 2;
|
||||
optional string error = 3;
|
||||
string service_method = 1;
|
||||
fixed64 seq = 2;
|
||||
string error = 3;
|
||||
}
|
||||
|
@@ -32,13 +32,13 @@ func (c *protoCodec) String() string {
|
||||
return "proto-rpc"
|
||||
}
|
||||
|
||||
func id(id string) *uint64 {
|
||||
func id(id string) uint64 {
|
||||
p, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
p = 0
|
||||
}
|
||||
i := uint64(p)
|
||||
return &i
|
||||
return i
|
||||
}
|
||||
|
||||
func (c *protoCodec) Write(m *codec.Message, b interface{}) error {
|
||||
@@ -47,7 +47,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
// This is protobuf, of course we copy it.
|
||||
pbr := &Request{ServiceMethod: &m.Method, Seq: id(m.Id)}
|
||||
pbr := &Request{ServiceMethod: m.Method, Seq: id(m.Id)}
|
||||
data, err := proto.Marshal(pbr)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -77,7 +77,7 @@ func (c *protoCodec) Write(m *codec.Message, b interface{}) error {
|
||||
case codec.Response, codec.Error:
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
rtmp := &Response{ServiceMethod: &m.Method, Seq: id(m.Id), Error: &m.Error}
|
||||
rtmp := &Response{ServiceMethod: m.Method, Seq: id(m.Id), Error: m.Error}
|
||||
data, err := proto.Marshal(rtmp)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@@ -8,11 +8,17 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/auth/provider"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/config"
|
||||
configSrv "github.com/micro/go-micro/v2/config/source/service"
|
||||
"github.com/micro/go-micro/v2/debug/profile"
|
||||
"github.com/micro/go-micro/v2/debug/profile/http"
|
||||
"github.com/micro/go-micro/v2/debug/profile/pprof"
|
||||
"github.com/micro/go-micro/v2/debug/trace"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/runtime"
|
||||
"github.com/micro/go-micro/v2/server"
|
||||
@@ -25,6 +31,7 @@ import (
|
||||
|
||||
// servers
|
||||
"github.com/micro/cli/v2"
|
||||
|
||||
sgrpc "github.com/micro/go-micro/v2/server/grpc"
|
||||
smucp "github.com/micro/go-micro/v2/server/mucp"
|
||||
|
||||
@@ -63,9 +70,11 @@ import (
|
||||
memTracer "github.com/micro/go-micro/v2/debug/trace/memory"
|
||||
|
||||
// auth
|
||||
jwtAuth "github.com/micro/go-micro/v2/auth/jwt"
|
||||
sAuth "github.com/micro/go-micro/v2/auth/service"
|
||||
storeAuth "github.com/micro/go-micro/v2/auth/store"
|
||||
svcAuth "github.com/micro/go-micro/v2/auth/service"
|
||||
|
||||
// auth providers
|
||||
"github.com/micro/go-micro/v2/auth/provider/basic"
|
||||
"github.com/micro/go-micro/v2/auth/provider/oauth"
|
||||
)
|
||||
|
||||
type Cmd interface {
|
||||
@@ -245,6 +254,11 @@ var (
|
||||
EnvVars: []string{"MICRO_AUTH"},
|
||||
Usage: "Auth for role based access control, e.g. service",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_token",
|
||||
EnvVars: []string{"MICRO_AUTH_TOKEN"},
|
||||
Usage: "Auth token used for client authentication",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_public_key",
|
||||
EnvVars: []string{"MICRO_AUTH_PUBLIC_KEY"},
|
||||
@@ -255,10 +269,40 @@ var (
|
||||
EnvVars: []string{"MICRO_AUTH_PRIVATE_KEY"},
|
||||
Usage: "Private key for JWT auth (base64 encoded PEM)",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "auth_exclude",
|
||||
EnvVars: []string{"MICRO_AUTH_EXCLUDE"},
|
||||
Usage: "Comma-separated list of endpoints excluded from authentication, e.g. Users.ListUsers",
|
||||
&cli.StringFlag{
|
||||
Name: "auth_provider",
|
||||
EnvVars: []string{"MICRO_AUTH_PROVIDER"},
|
||||
Usage: "Auth provider used to login user",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_provider_client_id",
|
||||
EnvVars: []string{"MICRO_AUTH_PROVIDER_CLIENT_ID"},
|
||||
Usage: "The client id to be used for oauth",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_provider_client_secret",
|
||||
EnvVars: []string{"MICRO_AUTH_PROVIDER_CLIENT_SECRET"},
|
||||
Usage: "The client secret to be used for oauth",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_provider_endpoint",
|
||||
EnvVars: []string{"MICRO_AUTH_PROVIDER_ENDPOINT"},
|
||||
Usage: "The enpoint to be used for oauth",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_provider_redirect",
|
||||
EnvVars: []string{"MICRO_AUTH_PROVIDER_REDIRECT"},
|
||||
Usage: "The redirect to be used for oauth",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth_provider_scope",
|
||||
EnvVars: []string{"MICRO_AUTH_PROVIDER_SCOPE"},
|
||||
Usage: "The scope to be used for oauth",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
EnvVars: []string{"MICRO_CONFIG"},
|
||||
Usage: "The source of the config to be used to get configuration",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -314,9 +358,21 @@ var (
|
||||
}
|
||||
|
||||
DefaultAuths = map[string]func(...auth.Option) auth.Auth{
|
||||
"service": sAuth.NewAuth,
|
||||
"store": storeAuth.NewAuth,
|
||||
"jwt": jwtAuth.NewAuth,
|
||||
"service": svcAuth.NewAuth,
|
||||
}
|
||||
|
||||
DefaultAuthProviders = map[string]func(...provider.Option) provider.Provider{
|
||||
"oauth": oauth.NewProvider,
|
||||
"basic": basic.NewProvider,
|
||||
}
|
||||
|
||||
DefaultProfiles = map[string]func(...profile.Option) profile.Profile{
|
||||
"http": http.NewProfile,
|
||||
"pprof": pprof.NewProfile,
|
||||
}
|
||||
|
||||
DefaultConfigs = map[string]func(...config.Option) (config.Config, error){
|
||||
"service": config.NewConfig,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -336,6 +392,8 @@ func newCmd(opts ...Option) Cmd {
|
||||
Runtime: &runtime.DefaultRuntime,
|
||||
Store: &store.DefaultStore,
|
||||
Tracer: &trace.DefaultTracer,
|
||||
Profile: &profile.DefaultProfile,
|
||||
Config: &config.DefaultConfig,
|
||||
|
||||
Brokers: DefaultBrokers,
|
||||
Clients: DefaultClients,
|
||||
@@ -347,6 +405,8 @@ func newCmd(opts ...Option) Cmd {
|
||||
Stores: DefaultStores,
|
||||
Tracers: DefaultTracers,
|
||||
Auths: DefaultAuths,
|
||||
Profiles: DefaultProfiles,
|
||||
Configs: DefaultConfigs,
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
@@ -430,6 +490,16 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
*c.opts.Auth = a()
|
||||
}
|
||||
|
||||
// Set the profile
|
||||
if name := ctx.String("profile"); len(name) > 0 {
|
||||
p, ok := c.opts.Profiles[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("Unsupported profile: %s", name)
|
||||
}
|
||||
|
||||
*c.opts.Profile = p()
|
||||
}
|
||||
|
||||
// Set the client
|
||||
if name := ctx.String("client"); len(name) > 0 {
|
||||
// only change if we have the client and type differs
|
||||
@@ -470,13 +540,13 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
clientOpts = append(clientOpts, client.Registry(*c.opts.Registry))
|
||||
|
||||
if err := (*c.opts.Selector).Init(selector.Registry(*c.opts.Registry)); err != nil {
|
||||
log.Fatalf("Error configuring registry: %v", err)
|
||||
logger.Fatalf("Error configuring registry: %v", err)
|
||||
}
|
||||
|
||||
clientOpts = append(clientOpts, client.Selector(*c.opts.Selector))
|
||||
|
||||
if err := (*c.opts.Broker).Init(broker.Registry(*c.opts.Registry)); err != nil {
|
||||
log.Fatalf("Error configuring broker: %v", err)
|
||||
logger.Fatalf("Error configuring broker: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,31 +593,31 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
|
||||
if len(ctx.String("broker_address")) > 0 {
|
||||
if err := (*c.opts.Broker).Init(broker.Addrs(strings.Split(ctx.String("broker_address"), ",")...)); err != nil {
|
||||
log.Fatalf("Error configuring broker: %v", err)
|
||||
logger.Fatalf("Error configuring broker: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ctx.String("registry_address")) > 0 {
|
||||
if err := (*c.opts.Registry).Init(registry.Addrs(strings.Split(ctx.String("registry_address"), ",")...)); err != nil {
|
||||
log.Fatalf("Error configuring registry: %v", err)
|
||||
logger.Fatalf("Error configuring registry: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ctx.String("transport_address")) > 0 {
|
||||
if err := (*c.opts.Transport).Init(transport.Addrs(strings.Split(ctx.String("transport_address"), ",")...)); err != nil {
|
||||
log.Fatalf("Error configuring transport: %v", err)
|
||||
logger.Fatalf("Error configuring transport: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ctx.String("store_address")) > 0 {
|
||||
if err := (*c.opts.Store).Init(store.Nodes(strings.Split(ctx.String("store_address"), ",")...)); err != nil {
|
||||
log.Fatalf("Error configuring store: %v", err)
|
||||
logger.Fatalf("Error configuring store: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ctx.String("store_namespace")) > 0 {
|
||||
if err := (*c.opts.Store).Init(store.Namespace(ctx.String("store_address"))); err != nil {
|
||||
log.Fatalf("Error configuring store: %v", err)
|
||||
if err := (*c.opts.Store).Init(store.Namespace(ctx.String("store_namespace"))); err != nil {
|
||||
logger.Fatalf("Error configuring store: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,10 +651,14 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
|
||||
if len(ctx.String("runtime_source")) > 0 {
|
||||
if err := (*c.opts.Runtime).Init(runtime.WithSource(ctx.String("runtime_source"))); err != nil {
|
||||
log.Fatalf("Error configuring runtime: %v", err)
|
||||
logger.Fatalf("Error configuring runtime: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ctx.String("auth_token")) > 0 {
|
||||
authOpts = append(authOpts, auth.ServiceToken(ctx.String("auth_token")))
|
||||
}
|
||||
|
||||
if len(ctx.String("auth_public_key")) > 0 {
|
||||
authOpts = append(authOpts, auth.PublicKey(ctx.String("auth_public_key")))
|
||||
}
|
||||
@@ -593,13 +667,37 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
authOpts = append(authOpts, auth.PrivateKey(ctx.String("auth_private_key")))
|
||||
}
|
||||
|
||||
if len(ctx.StringSlice("auth_exclude")) > 0 {
|
||||
authOpts = append(authOpts, auth.Excludes(ctx.StringSlice("auth_exclude")...))
|
||||
}
|
||||
if name := ctx.String("auth_provider"); len(name) > 0 {
|
||||
p, ok := DefaultAuthProviders[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("AuthProvider %s not found", name)
|
||||
}
|
||||
|
||||
if len(authOpts) > 0 {
|
||||
if err := (*c.opts.Auth).Init(authOpts...); err != nil {
|
||||
log.Fatalf("Error configuring auth: %v", err)
|
||||
var provOpts []provider.Option
|
||||
|
||||
clientID := ctx.String("auth_provider_client_id")
|
||||
clientSecret := ctx.String("auth_provider_client_secret")
|
||||
if len(clientID) > 0 || len(clientSecret) > 0 {
|
||||
provOpts = append(provOpts, provider.Credentials(clientID, clientSecret))
|
||||
}
|
||||
if e := ctx.String("auth_provider_endpoint"); len(e) > 0 {
|
||||
provOpts = append(provOpts, provider.Endpoint(e))
|
||||
}
|
||||
if r := ctx.String("auth_provider_redirect"); len(r) > 0 {
|
||||
provOpts = append(provOpts, provider.Redirect(r))
|
||||
}
|
||||
if s := ctx.String("auth_provider_scope"); len(s) > 0 {
|
||||
provOpts = append(provOpts, provider.Scope(s))
|
||||
}
|
||||
|
||||
authOpts = append(authOpts, auth.Provider(p(provOpts...)))
|
||||
}
|
||||
(*c.opts.Auth).Init(authOpts...)
|
||||
|
||||
if ctx.String("config") == "service" {
|
||||
opt := config.WithSource(configSrv.NewSource())
|
||||
if err := (*c.opts.Config).Init(opt); err != nil {
|
||||
logger.Fatalf("Error configuring config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,14 +730,14 @@ func (c *cmd) Before(ctx *cli.Context) error {
|
||||
// Lets set it up
|
||||
if len(serverOpts) > 0 {
|
||||
if err := (*c.opts.Server).Init(serverOpts...); err != nil {
|
||||
log.Fatalf("Error configuring server: %v", err)
|
||||
logger.Fatalf("Error configuring server: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Use an init option?
|
||||
if len(clientOpts) > 0 {
|
||||
if err := (*c.opts.Client).Init(clientOpts...); err != nil {
|
||||
log.Fatalf("Error configuring client: %v", err)
|
||||
logger.Fatalf("Error configuring client: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/config"
|
||||
"github.com/micro/go-micro/v2/debug/profile"
|
||||
"github.com/micro/go-micro/v2/debug/trace"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/runtime"
|
||||
@@ -26,14 +28,17 @@ type Options struct {
|
||||
Registry *registry.Registry
|
||||
Selector *selector.Selector
|
||||
Transport *transport.Transport
|
||||
Config *config.Config
|
||||
Client *client.Client
|
||||
Server *server.Server
|
||||
Runtime *runtime.Runtime
|
||||
Store *store.Store
|
||||
Tracer *trace.Tracer
|
||||
Auth *auth.Auth
|
||||
Profile *profile.Profile
|
||||
|
||||
Brokers map[string]func(...broker.Option) broker.Broker
|
||||
Configs map[string]func(...config.Option) (config.Config, error)
|
||||
Clients map[string]func(...client.Option) client.Client
|
||||
Registries map[string]func(...registry.Option) registry.Registry
|
||||
Selectors map[string]func(...selector.Option) selector.Selector
|
||||
@@ -43,6 +48,7 @@ type Options struct {
|
||||
Stores map[string]func(...store.Option) store.Store
|
||||
Tracers map[string]func(...trace.Option) trace.Tracer
|
||||
Auths map[string]func(...auth.Option) auth.Auth
|
||||
Profiles map[string]func(...profile.Option) profile.Profile
|
||||
|
||||
// Other options for implementations of the interface
|
||||
// can be stored in a context
|
||||
@@ -76,6 +82,12 @@ func Broker(b *broker.Broker) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func Config(c *config.Config) Option {
|
||||
return func(o *Options) {
|
||||
o.Config = c
|
||||
}
|
||||
}
|
||||
|
||||
func Selector(s *selector.Selector) Option {
|
||||
return func(o *Options) {
|
||||
o.Selector = s
|
||||
@@ -118,6 +130,12 @@ func Auth(a *auth.Auth) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func Profile(p *profile.Profile) Option {
|
||||
return func(o *Options) {
|
||||
o.Profile = p
|
||||
}
|
||||
}
|
||||
|
||||
// New broker func
|
||||
func NewBroker(name string, b func(...broker.Option) broker.Broker) Option {
|
||||
return func(o *Options) {
|
||||
|
@@ -14,6 +14,8 @@ import (
|
||||
type Config interface {
|
||||
// provide the reader.Values interface
|
||||
reader.Values
|
||||
// Init the config
|
||||
Init(opts ...Option) error
|
||||
// Stop the config loader/watcher
|
||||
Close() error
|
||||
// Load config sources
|
||||
|
@@ -31,38 +31,40 @@ type watcher struct {
|
||||
}
|
||||
|
||||
func newConfig(opts ...Option) (Config, error) {
|
||||
options := Options{
|
||||
var c config
|
||||
|
||||
c.Init(opts...)
|
||||
go c.run()
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
func (c *config) Init(opts ...Option) error {
|
||||
c.opts = Options{
|
||||
Loader: memory.NewLoader(),
|
||||
Reader: json.NewReader(),
|
||||
}
|
||||
|
||||
c.exit = make(chan bool)
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
o(&c.opts)
|
||||
}
|
||||
|
||||
if err := options.Loader.Load(options.Source...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
snap, err := options.Loader.Snapshot()
|
||||
err := c.opts.Loader.Load(c.opts.Source...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
vals, err := options.Reader.Values(snap.ChangeSet)
|
||||
|
||||
c.snap, err = c.opts.Loader.Snapshot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
c := &config{
|
||||
exit: make(chan bool),
|
||||
opts: options,
|
||||
snap: snap,
|
||||
vals: vals,
|
||||
c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go c.run()
|
||||
|
||||
return c, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *config) run() {
|
||||
|
@@ -12,10 +12,6 @@ import (
|
||||
"github.com/micro/go-micro/v2/config/source/file"
|
||||
)
|
||||
|
||||
var (
|
||||
sep = string(os.PathSeparator)
|
||||
)
|
||||
|
||||
func createFileForIssue18(t *testing.T, content string) *os.File {
|
||||
data := []byte(content)
|
||||
path := filepath.Join(os.TempDir(), fmt.Sprintf("file.%d", time.Now().UnixNano()))
|
||||
|
@@ -1,34 +0,0 @@
|
||||
package options
|
||||
|
||||
type defaultOptions struct {
|
||||
opts *Values
|
||||
}
|
||||
|
||||
type stringKey struct{}
|
||||
|
||||
func (d *defaultOptions) Init(opts ...Option) error {
|
||||
if d.opts == nil {
|
||||
d.opts = new(Values)
|
||||
}
|
||||
for _, o := range opts {
|
||||
if err := d.opts.Option(o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *defaultOptions) Values() *Values {
|
||||
return d.opts
|
||||
}
|
||||
|
||||
func (d *defaultOptions) String() string {
|
||||
if d.opts == nil {
|
||||
d.opts = new(Values)
|
||||
}
|
||||
n, ok := d.opts.Get(stringKey{})
|
||||
if ok {
|
||||
return n.(string)
|
||||
}
|
||||
return "Values"
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
// Package options provides a way to initialise options
|
||||
package options
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Options is used for initialisation
|
||||
type Options interface {
|
||||
// Initialise options
|
||||
Init(...Option) error
|
||||
// Options returns the current options
|
||||
Values() *Values
|
||||
// The name for who these options exist
|
||||
String() string
|
||||
}
|
||||
|
||||
// Values holds the set of option values and protects them
|
||||
type Values struct {
|
||||
sync.RWMutex
|
||||
values map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// Option gives access to options
|
||||
type Option func(o *Values) error
|
||||
|
||||
// Get a value from options
|
||||
func (o *Values) Get(k interface{}) (interface{}, bool) {
|
||||
o.RLock()
|
||||
defer o.RUnlock()
|
||||
v, ok := o.values[k]
|
||||
return v, ok
|
||||
}
|
||||
|
||||
// Set a value in the options
|
||||
func (o *Values) Set(k, v interface{}) error {
|
||||
o.Lock()
|
||||
defer o.Unlock()
|
||||
if o.values == nil {
|
||||
o.values = map[interface{}]interface{}{}
|
||||
}
|
||||
o.values[k] = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetOption executes an option
|
||||
func (o *Values) Option(op Option) error {
|
||||
return op(o)
|
||||
}
|
||||
|
||||
// WithValue allows you to set any value within the options
|
||||
func WithValue(k, v interface{}) Option {
|
||||
return func(o *Values) error {
|
||||
return o.Set(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// WithOption gives you the ability to create an option that accesses values
|
||||
func WithOption(o Option) Option {
|
||||
return o
|
||||
}
|
||||
|
||||
// String sets the string
|
||||
func WithString(s string) Option {
|
||||
return WithValue(stringKey{}, s)
|
||||
}
|
||||
|
||||
// NewOptions returns a new initialiser
|
||||
func NewOptions(opts ...Option) Options {
|
||||
o := new(defaultOptions)
|
||||
if err := o.Init(opts...); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return o
|
||||
}
|
89
config/secrets/box/box.go
Normal file
89
config/secrets/box/box.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// Package box is an asymmetric implementation of config/secrets using nacl/box
|
||||
package box
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/v2/config/secrets"
|
||||
"github.com/pkg/errors"
|
||||
naclbox "golang.org/x/crypto/nacl/box"
|
||||
|
||||
"crypto/rand"
|
||||
)
|
||||
|
||||
const keyLength = 32
|
||||
|
||||
type box struct {
|
||||
options secrets.Options
|
||||
|
||||
publicKey [keyLength]byte
|
||||
privateKey [keyLength]byte
|
||||
}
|
||||
|
||||
// NewCodec returns a nacl-box codec
|
||||
func NewCodec(opts ...secrets.Option) secrets.Codec {
|
||||
b := &box{}
|
||||
for _, o := range opts {
|
||||
o(&b.options)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Init initialises a box
|
||||
func (b *box) Init(opts ...secrets.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&b.options)
|
||||
}
|
||||
if len(b.options.PrivateKey) != keyLength || len(b.options.PublicKey) != keyLength {
|
||||
return errors.Errorf("a public key and a private key of length %d must both be provided", keyLength)
|
||||
}
|
||||
copy(b.privateKey[:], b.options.PrivateKey)
|
||||
copy(b.publicKey[:], b.options.PublicKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Options returns options
|
||||
func (b *box) Options() secrets.Options {
|
||||
return b.options
|
||||
}
|
||||
|
||||
// String returns nacl-box
|
||||
func (*box) String() string {
|
||||
return "nacl-box"
|
||||
}
|
||||
|
||||
// Encrypt encrypts a message with the sender's private key and the receipient's public key
|
||||
func (b *box) Encrypt(in []byte, opts ...secrets.EncryptOption) ([]byte, error) {
|
||||
var options secrets.EncryptOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
if len(options.RecipientPublicKey) != keyLength {
|
||||
return []byte{}, errors.New("recepient's public key must be provided")
|
||||
}
|
||||
var recipientPublicKey [keyLength]byte
|
||||
copy(recipientPublicKey[:], options.RecipientPublicKey)
|
||||
var nonce [24]byte
|
||||
if _, err := rand.Reader.Read(nonce[:]); err != nil {
|
||||
return []byte{}, errors.Wrap(err, "couldn't obtain a random nonce from crypto/rand")
|
||||
}
|
||||
return naclbox.Seal(nonce[:], in, &nonce, &recipientPublicKey, &b.privateKey), nil
|
||||
}
|
||||
|
||||
// Decrypt Decrypts a message with the receiver's private key and the sender's public key
|
||||
func (b *box) Decrypt(in []byte, opts ...secrets.DecryptOption) ([]byte, error) {
|
||||
var options secrets.DecryptOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
if len(options.SenderPublicKey) != keyLength {
|
||||
return []byte{}, errors.New("sender's public key bust be provided")
|
||||
}
|
||||
var nonce [24]byte
|
||||
var senderPublicKey [32]byte
|
||||
copy(nonce[:], in[:24])
|
||||
copy(senderPublicKey[:], options.SenderPublicKey)
|
||||
decrypted, ok := naclbox.Open(nil, in[24:], &nonce, &senderPublicKey, &b.privateKey)
|
||||
if !ok {
|
||||
return []byte{}, errors.New("incoming message couldn't be verified / decrypted")
|
||||
}
|
||||
return decrypted, nil
|
||||
}
|
63
config/secrets/box/box_test.go
Normal file
63
config/secrets/box/box_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package box
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/v2/config/secrets"
|
||||
naclbox "golang.org/x/crypto/nacl/box"
|
||||
)
|
||||
|
||||
func TestBox(t *testing.T) {
|
||||
alicePublicKey, alicePrivateKey, err := naclbox.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bobPublicKey, bobPrivateKey, err := naclbox.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
alice, bob := NewCodec(secrets.PublicKey(alicePublicKey[:]), secrets.PrivateKey(alicePrivateKey[:])), NewCodec()
|
||||
if err := alice.Init(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := bob.Init(secrets.PublicKey(bobPublicKey[:]), secrets.PrivateKey(bobPrivateKey[:])); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if alice.String() != "nacl-box" {
|
||||
t.Error("String() doesn't return nacl-box")
|
||||
}
|
||||
aliceSecret := []byte("Why is a raven like a writing-desk?")
|
||||
if _, err := alice.Encrypt(aliceSecret); err == nil {
|
||||
t.Error("alice.Encrypt succeded without a public key")
|
||||
}
|
||||
enc, err := alice.Encrypt(aliceSecret, secrets.RecipientPublicKey(bob.Options().PublicKey))
|
||||
if err != nil {
|
||||
t.Error("alice.Encrypt failed")
|
||||
}
|
||||
if _, err := bob.Decrypt(enc); err == nil {
|
||||
t.Error("bob.Decrypt succeded without a public key")
|
||||
}
|
||||
if dec, err := bob.Decrypt(enc, secrets.SenderPublicKey(alice.Options().PublicKey)); err == nil {
|
||||
if !reflect.DeepEqual(dec, aliceSecret) {
|
||||
t.Errorf("Bob's decrypted message didn't match Alice's encrypted message: %v != %v", aliceSecret, dec)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("bob.Decrypt failed (%s)", err)
|
||||
}
|
||||
|
||||
bobSecret := []byte("I haven't the slightest idea")
|
||||
enc, err = bob.Encrypt(bobSecret, secrets.RecipientPublicKey(alice.Options().PublicKey))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
dec, err := alice.Decrypt(enc, secrets.SenderPublicKey(bob.Options().PrivateKey))
|
||||
if err == nil {
|
||||
t.Error(err)
|
||||
}
|
||||
dec, err = alice.Decrypt(enc, secrets.SenderPublicKey(bob.Options().PublicKey))
|
||||
if !reflect.DeepEqual(dec, bobSecret) {
|
||||
t.Errorf("Alice's decrypted message didn't match Bob's encrypted message %v != %v", bobSecret, dec)
|
||||
}
|
||||
}
|
73
config/secrets/secretbox/secretbox.go
Normal file
73
config/secrets/secretbox/secretbox.go
Normal file
@@ -0,0 +1,73 @@
|
||||
// Package secretbox is a config/secrets implementation that uses nacl/secretbox
|
||||
// to do symmetric encryption / verification
|
||||
package secretbox
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/v2/config/secrets"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
|
||||
"crypto/rand"
|
||||
)
|
||||
|
||||
const keyLength = 32
|
||||
|
||||
type secretBox struct {
|
||||
options secrets.Options
|
||||
|
||||
secretKey [keyLength]byte
|
||||
}
|
||||
|
||||
// NewCodec returns a secretbox codec
|
||||
func NewCodec(opts ...secrets.Option) secrets.Codec {
|
||||
sb := &secretBox{}
|
||||
for _, o := range opts {
|
||||
o(&sb.options)
|
||||
}
|
||||
return sb
|
||||
}
|
||||
|
||||
func (s *secretBox) Init(opts ...secrets.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
if len(s.options.SecretKey) == 0 {
|
||||
return errors.New("no secret key is defined")
|
||||
}
|
||||
if len(s.options.SecretKey) != keyLength {
|
||||
return errors.Errorf("secret key must be %d bytes long", keyLength)
|
||||
}
|
||||
copy(s.secretKey[:], s.options.SecretKey)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *secretBox) Options() secrets.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
func (s *secretBox) String() string {
|
||||
return "nacl-secretbox"
|
||||
}
|
||||
|
||||
func (s *secretBox) Encrypt(in []byte, opts ...secrets.EncryptOption) ([]byte, error) {
|
||||
// no opts are expected, so they are ignored
|
||||
|
||||
// there must be a unique nonce for each message
|
||||
var nonce [24]byte
|
||||
if _, err := rand.Reader.Read(nonce[:]); err != nil {
|
||||
return []byte{}, errors.Wrap(err, "couldn't obtain a random nonce from crypto/rand")
|
||||
}
|
||||
return secretbox.Seal(nonce[:], in, &nonce, &s.secretKey), nil
|
||||
}
|
||||
|
||||
func (s *secretBox) Decrypt(in []byte, opts ...secrets.DecryptOption) ([]byte, error) {
|
||||
// no options are expected, so they are ignored
|
||||
|
||||
var decryptNonce [24]byte
|
||||
copy(decryptNonce[:], in[:24])
|
||||
decrypted, ok := secretbox.Open(nil, in[24:], &decryptNonce, &s.secretKey)
|
||||
if !ok {
|
||||
return []byte{}, errors.New("decryption failed (is the key set correctly?)")
|
||||
}
|
||||
return decrypted, nil
|
||||
}
|
56
config/secrets/secretbox/secretbox_test.go
Normal file
56
config/secrets/secretbox/secretbox_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package secretbox
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/v2/config/secrets"
|
||||
)
|
||||
|
||||
func TestSecretBox(t *testing.T) {
|
||||
secretKey, err := base64.StdEncoding.DecodeString("4jbVgq8FsAV7vy+n8WqEZrl7BUtNqh3fYT5RXzXOPFY=")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s := NewCodec()
|
||||
|
||||
if err := s.Init(); err == nil {
|
||||
t.Error("Secretbox accepted an empty secret key")
|
||||
}
|
||||
if err := s.Init(secrets.SecretKey([]byte("invalid"))); err == nil {
|
||||
t.Error("Secretbox accepted a secret key that is invalid")
|
||||
}
|
||||
|
||||
if err := s.Init(secrets.SecretKey(secretKey)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
o := s.Options()
|
||||
if !reflect.DeepEqual(o.SecretKey, secretKey) {
|
||||
t.Error("Init() didn't set secret key correctly")
|
||||
}
|
||||
if s.String() != "nacl-secretbox" {
|
||||
t.Error(s.String() + " should be nacl-secretbox")
|
||||
}
|
||||
|
||||
// Try 10 times to get different nonces
|
||||
for i := 0; i < 10; i++ {
|
||||
message := []byte(`Can you hear me, Major Tom?`)
|
||||
|
||||
encrypted, err := s.Encrypt(message)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to encrypt message (%s)", err)
|
||||
}
|
||||
|
||||
decrypted, err := s.Decrypt(encrypted)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to decrypt encrypted message (%s)", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(message, decrypted) {
|
||||
t.Errorf("Decrypted Message dod not match encrypted message")
|
||||
}
|
||||
}
|
||||
}
|
82
config/secrets/secrets.go
Normal file
82
config/secrets/secrets.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Package secrets is an interface for encrypting and decrypting secrets
|
||||
package secrets
|
||||
|
||||
import "context"
|
||||
|
||||
// Codec encrypts or decrypts arbitrary data. The data should be as small as possible
|
||||
type Codec interface {
|
||||
Init(...Option) error
|
||||
Options() Options
|
||||
String() string
|
||||
Decrypt([]byte, ...DecryptOption) ([]byte, error)
|
||||
Encrypt([]byte, ...EncryptOption) ([]byte, error)
|
||||
}
|
||||
|
||||
// Options is a codec's options
|
||||
// SecretKey or both PublicKey and PrivateKey should be set depending on the
|
||||
// underlying implementation
|
||||
type Options struct {
|
||||
SecretKey []byte
|
||||
PrivateKey []byte
|
||||
PublicKey []byte
|
||||
Context context.Context
|
||||
}
|
||||
|
||||
// Option sets options
|
||||
type Option func(*Options)
|
||||
|
||||
// SecretKey sets the symmetric secret key
|
||||
func SecretKey(key []byte) Option {
|
||||
return func(o *Options) {
|
||||
o.SecretKey = make([]byte, len(key))
|
||||
copy(o.SecretKey, key)
|
||||
}
|
||||
}
|
||||
|
||||
// PublicKey sets the asymmetric Public Key of this codec
|
||||
func PublicKey(key []byte) Option {
|
||||
return func(o *Options) {
|
||||
o.PublicKey = make([]byte, len(key))
|
||||
copy(o.PublicKey, key)
|
||||
}
|
||||
}
|
||||
|
||||
// PrivateKey sets the asymmetric Private Key of this codec
|
||||
func PrivateKey(key []byte) Option {
|
||||
return func(o *Options) {
|
||||
o.PrivateKey = make([]byte, len(key))
|
||||
copy(o.PrivateKey, key)
|
||||
}
|
||||
}
|
||||
|
||||
// DecryptOptions can be passed to Codec.Decrypt
|
||||
type DecryptOptions struct {
|
||||
SenderPublicKey []byte
|
||||
}
|
||||
|
||||
// DecryptOption sets DecryptOptions
|
||||
type DecryptOption func(*DecryptOptions)
|
||||
|
||||
// SenderPublicKey is the Public Key of the Codec that encrypted this message
|
||||
func SenderPublicKey(key []byte) DecryptOption {
|
||||
return func(d *DecryptOptions) {
|
||||
d.SenderPublicKey = make([]byte, len(key))
|
||||
copy(d.SenderPublicKey, key)
|
||||
}
|
||||
}
|
||||
|
||||
// EncryptOptions can be passed to Codec.Encrypt
|
||||
type EncryptOptions struct {
|
||||
RecipientPublicKey []byte
|
||||
}
|
||||
|
||||
// EncryptOption Sets EncryptOptions
|
||||
type EncryptOption func(*EncryptOptions)
|
||||
|
||||
// RecipientPublicKey is the Public Key of the Codec that will decrypt this message
|
||||
func RecipientPublicKey(key []byte) EncryptOption {
|
||||
return func(e *EncryptOptions) {
|
||||
e.RecipientPublicKey = make([]byte, len(key))
|
||||
copy(e.RecipientPublicKey, key)
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package file
|
||||
package file_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -6,8 +6,37 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/config"
|
||||
"github.com/micro/go-micro/v2/config/source/file"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
data := []byte(`{"foo": "bar"}`)
|
||||
path := filepath.Join(os.TempDir(), fmt.Sprintf("file.%d", time.Now().UnixNano()))
|
||||
fh, err := os.Create(path)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
defer func() {
|
||||
fh.Close()
|
||||
os.Remove(path)
|
||||
}()
|
||||
_, err = fh.Write(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
conf, err := config.NewConfig()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conf.Load(file.NewSource(file.WithPath(path)))
|
||||
// simulate multiple close
|
||||
go conf.Close()
|
||||
go conf.Close()
|
||||
}
|
||||
|
||||
func TestFile(t *testing.T) {
|
||||
data := []byte(`{"foo": "bar"}`)
|
||||
path := filepath.Join(os.TempDir(), fmt.Sprintf("file.%d", time.Now().UnixNano()))
|
||||
@@ -25,7 +54,7 @@ func TestFile(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
f := NewSource(WithPath(path))
|
||||
f := file.NewSource(file.WithPath(path))
|
||||
c, err := f.Read()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type serviceNameKey struct{}
|
||||
type keyKey struct{}
|
||||
type namespaceKey struct{}
|
||||
type pathKey struct{}
|
||||
|
||||
func ServiceName(name string) source.Option {
|
||||
@@ -19,12 +19,12 @@ func ServiceName(name string) source.Option {
|
||||
}
|
||||
}
|
||||
|
||||
func Key(key string) source.Option {
|
||||
func Namespace(namespace string) source.Option {
|
||||
return func(o *source.Options) {
|
||||
if o.Context == nil {
|
||||
o.Context = context.Background()
|
||||
}
|
||||
o.Context = context.WithValue(o.Context, keyKey{}, key)
|
||||
o.Context = context.WithValue(o.Context, namespaceKey{}, namespace)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,15 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: go-micro/config/source/service/proto/service.proto
|
||||
// source: config/source/service/proto/service.proto
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
@@ -21,7 +25,7 @@ var _ = math.Inf
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type ChangeSet struct {
|
||||
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
Checksum string `protobuf:"bytes,2,opt,name=checksum,proto3" json:"checksum,omitempty"`
|
||||
Format string `protobuf:"bytes,3,opt,name=format,proto3" json:"format,omitempty"`
|
||||
Source string `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"`
|
||||
@@ -35,7 +39,7 @@ func (m *ChangeSet) Reset() { *m = ChangeSet{} }
|
||||
func (m *ChangeSet) String() string { return proto.CompactTextString(m) }
|
||||
func (*ChangeSet) ProtoMessage() {}
|
||||
func (*ChangeSet) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{0}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{0}
|
||||
}
|
||||
|
||||
func (m *ChangeSet) XXX_Unmarshal(b []byte) error {
|
||||
@@ -56,11 +60,11 @@ func (m *ChangeSet) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_ChangeSet proto.InternalMessageInfo
|
||||
|
||||
func (m *ChangeSet) GetData() []byte {
|
||||
func (m *ChangeSet) GetData() string {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ChangeSet) GetChecksum() string {
|
||||
@@ -92,7 +96,7 @@ func (m *ChangeSet) GetTimestamp() int64 {
|
||||
}
|
||||
|
||||
type Change struct {
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||
ChangeSet *ChangeSet `protobuf:"bytes,3,opt,name=changeSet,proto3" json:"changeSet,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
@@ -104,7 +108,7 @@ func (m *Change) Reset() { *m = Change{} }
|
||||
func (m *Change) String() string { return proto.CompactTextString(m) }
|
||||
func (*Change) ProtoMessage() {}
|
||||
func (*Change) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{1}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{1}
|
||||
}
|
||||
|
||||
func (m *Change) XXX_Unmarshal(b []byte) error {
|
||||
@@ -125,9 +129,9 @@ func (m *Change) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_Change proto.InternalMessageInfo
|
||||
|
||||
func (m *Change) GetKey() string {
|
||||
func (m *Change) GetNamespace() string {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
return m.Namespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -157,7 +161,7 @@ func (m *CreateRequest) Reset() { *m = CreateRequest{} }
|
||||
func (m *CreateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*CreateRequest) ProtoMessage() {}
|
||||
func (*CreateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{2}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{2}
|
||||
}
|
||||
|
||||
func (m *CreateRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -195,7 +199,7 @@ func (m *CreateResponse) Reset() { *m = CreateResponse{} }
|
||||
func (m *CreateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*CreateResponse) ProtoMessage() {}
|
||||
func (*CreateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{3}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{3}
|
||||
}
|
||||
|
||||
func (m *CreateResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -227,7 +231,7 @@ func (m *UpdateRequest) Reset() { *m = UpdateRequest{} }
|
||||
func (m *UpdateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*UpdateRequest) ProtoMessage() {}
|
||||
func (*UpdateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{4}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{4}
|
||||
}
|
||||
|
||||
func (m *UpdateRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -265,7 +269,7 @@ func (m *UpdateResponse) Reset() { *m = UpdateResponse{} }
|
||||
func (m *UpdateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*UpdateResponse) ProtoMessage() {}
|
||||
func (*UpdateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{5}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{5}
|
||||
}
|
||||
|
||||
func (m *UpdateResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -297,7 +301,7 @@ func (m *DeleteRequest) Reset() { *m = DeleteRequest{} }
|
||||
func (m *DeleteRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteRequest) ProtoMessage() {}
|
||||
func (*DeleteRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{6}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{6}
|
||||
}
|
||||
|
||||
func (m *DeleteRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -335,7 +339,7 @@ func (m *DeleteResponse) Reset() { *m = DeleteResponse{} }
|
||||
func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteResponse) ProtoMessage() {}
|
||||
func (*DeleteResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{7}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{7}
|
||||
}
|
||||
|
||||
func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -366,7 +370,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} }
|
||||
func (m *ListRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListRequest) ProtoMessage() {}
|
||||
func (*ListRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{8}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{8}
|
||||
}
|
||||
|
||||
func (m *ListRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -398,7 +402,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} }
|
||||
func (m *ListResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ListResponse) ProtoMessage() {}
|
||||
func (*ListResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{9}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{9}
|
||||
}
|
||||
|
||||
func (m *ListResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -427,7 +431,7 @@ func (m *ListResponse) GetValues() []*Change {
|
||||
}
|
||||
|
||||
type ReadRequest struct {
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@@ -438,7 +442,7 @@ func (m *ReadRequest) Reset() { *m = ReadRequest{} }
|
||||
func (m *ReadRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReadRequest) ProtoMessage() {}
|
||||
func (*ReadRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{10}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{10}
|
||||
}
|
||||
|
||||
func (m *ReadRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -459,9 +463,9 @@ func (m *ReadRequest) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_ReadRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *ReadRequest) GetKey() string {
|
||||
func (m *ReadRequest) GetNamespace() string {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
return m.Namespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -484,7 +488,7 @@ func (m *ReadResponse) Reset() { *m = ReadResponse{} }
|
||||
func (m *ReadResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReadResponse) ProtoMessage() {}
|
||||
func (*ReadResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{11}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{11}
|
||||
}
|
||||
|
||||
func (m *ReadResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -513,7 +517,7 @@ func (m *ReadResponse) GetChange() *Change {
|
||||
}
|
||||
|
||||
type WatchRequest struct {
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@@ -524,7 +528,7 @@ func (m *WatchRequest) Reset() { *m = WatchRequest{} }
|
||||
func (m *WatchRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*WatchRequest) ProtoMessage() {}
|
||||
func (*WatchRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{12}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{12}
|
||||
}
|
||||
|
||||
func (m *WatchRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -545,9 +549,9 @@ func (m *WatchRequest) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_WatchRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *WatchRequest) GetKey() string {
|
||||
func (m *WatchRequest) GetNamespace() string {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
return m.Namespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -560,7 +564,7 @@ func (m *WatchRequest) GetPath() string {
|
||||
}
|
||||
|
||||
type WatchResponse struct {
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
ChangeSet *ChangeSet `protobuf:"bytes,2,opt,name=changeSet,proto3" json:"changeSet,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
@@ -571,7 +575,7 @@ func (m *WatchResponse) Reset() { *m = WatchResponse{} }
|
||||
func (m *WatchResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*WatchResponse) ProtoMessage() {}
|
||||
func (*WatchResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_05971a9aaecb0484, []int{13}
|
||||
return fileDescriptor_e67338fe1f659d14, []int{13}
|
||||
}
|
||||
|
||||
func (m *WatchResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -592,9 +596,9 @@ func (m *WatchResponse) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_WatchResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *WatchResponse) GetKey() string {
|
||||
func (m *WatchResponse) GetNamespace() string {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
return m.Namespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -624,37 +628,325 @@ func init() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("go-micro/config/source/service/proto/service.proto", fileDescriptor_05971a9aaecb0484)
|
||||
proto.RegisterFile("config/source/service/proto/service.proto", fileDescriptor_e67338fe1f659d14)
|
||||
}
|
||||
|
||||
var fileDescriptor_05971a9aaecb0484 = []byte{
|
||||
// 443 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0xcf, 0x6a, 0xdb, 0x40,
|
||||
0x10, 0xc6, 0x2d, 0xdb, 0x51, 0xab, 0xb1, 0x24, 0x87, 0x39, 0x14, 0x21, 0x0a, 0x35, 0x82, 0x82,
|
||||
0x69, 0xe9, 0x2a, 0x38, 0x7d, 0x03, 0xf7, 0xd6, 0x9e, 0x54, 0x4a, 0x7b, 0xdd, 0xca, 0x13, 0x5b,
|
||||
0x24, 0xf2, 0xaa, 0xda, 0x75, 0xa0, 0x8f, 0x90, 0xb7, 0x2e, 0xfb, 0x47, 0xb1, 0xe4, 0x82, 0x89,
|
||||
0x6f, 0x3b, 0x33, 0x3b, 0xdf, 0x7c, 0x9a, 0x9f, 0x16, 0x56, 0x5b, 0xf1, 0xa9, 0xae, 0xca, 0x56,
|
||||
0xe4, 0xa5, 0xd8, 0xdf, 0x55, 0xdb, 0x5c, 0x8a, 0x43, 0x5b, 0x52, 0x2e, 0xa9, 0x7d, 0xac, 0x4a,
|
||||
0xca, 0x9b, 0x56, 0x28, 0xd1, 0x45, 0xcc, 0x44, 0xd9, 0x93, 0x07, 0xc1, 0x7a, 0xc7, 0xf7, 0x5b,
|
||||
0xfa, 0x4e, 0x0a, 0x11, 0xa6, 0x1b, 0xae, 0x78, 0xe2, 0x2d, 0xbc, 0x65, 0x58, 0x98, 0x33, 0xa6,
|
||||
0xf0, 0xba, 0xdc, 0x51, 0x79, 0x2f, 0x0f, 0x75, 0x32, 0x5e, 0x78, 0xcb, 0xa0, 0x78, 0x8e, 0xf1,
|
||||
0x0d, 0xf8, 0x77, 0xa2, 0xad, 0xb9, 0x4a, 0x26, 0xa6, 0xe2, 0x22, 0x9d, 0xb7, 0xb3, 0x93, 0xa9,
|
||||
0xcd, 0xdb, 0x08, 0xdf, 0x42, 0xa0, 0xaa, 0x9a, 0xa4, 0xe2, 0x75, 0x93, 0x5c, 0x2d, 0xbc, 0xe5,
|
||||
0xa4, 0x38, 0x26, 0xb2, 0x5f, 0xe0, 0x5b, 0x2b, 0x78, 0x0d, 0x93, 0x7b, 0xfa, 0x6b, 0x6c, 0x04,
|
||||
0x85, 0x3e, 0x6a, 0x67, 0x0d, 0x57, 0x3b, 0xe7, 0xc0, 0x9c, 0x71, 0x09, 0x41, 0xd9, 0x59, 0x37,
|
||||
0x06, 0x66, 0x2b, 0x60, 0xcf, 0x1f, 0x53, 0x1c, 0x8b, 0xd9, 0x0d, 0x44, 0xeb, 0x96, 0xb8, 0xa2,
|
||||
0x82, 0xfe, 0x1c, 0x48, 0x2a, 0x7c, 0x07, 0xbe, 0xad, 0x9a, 0x19, 0xb3, 0xd5, 0x2b, 0xd7, 0x57,
|
||||
0xb8, 0x74, 0x76, 0x0d, 0x71, 0xd7, 0x21, 0x1b, 0xb1, 0x97, 0xa4, 0x35, 0x7e, 0x34, 0x9b, 0x0b,
|
||||
0x35, 0xba, 0x8e, 0xa3, 0xc6, 0x17, 0x7a, 0xa0, 0xcb, 0x34, 0xba, 0x0e, 0xa7, 0x11, 0xc1, 0xec,
|
||||
0x5b, 0x25, 0x95, 0x53, 0xc8, 0x72, 0x08, 0x6d, 0x68, 0xcb, 0x5a, 0xf1, 0x91, 0x3f, 0x1c, 0x48,
|
||||
0x26, 0xde, 0x62, 0x32, 0x50, 0xb4, 0xe9, 0xec, 0x16, 0x66, 0x05, 0xf1, 0x4d, 0xe7, 0xe0, 0x45,
|
||||
0xab, 0xd6, 0x53, 0x6c, 0xd3, 0x71, 0xca, 0x79, 0xdf, 0x9f, 0x21, 0xfc, 0xc9, 0x55, 0xb9, 0xbb,
|
||||
0x6c, 0xcc, 0x57, 0x88, 0x5c, 0x97, 0x9b, 0xf3, 0x7f, 0xdb, 0x00, 0xfa, 0xf8, 0x0c, 0xf4, 0xd5,
|
||||
0xd3, 0x18, 0xfc, 0xb5, 0x79, 0x08, 0xf8, 0x11, 0x7c, 0x4b, 0x13, 0x63, 0x36, 0xf8, 0x11, 0xd2,
|
||||
0x39, 0x3b, 0xc1, 0x3c, 0xd2, 0x97, 0x2d, 0x36, 0x8c, 0xd9, 0x80, 0x78, 0x3a, 0x67, 0x27, 0x3c,
|
||||
0xcd, 0x65, 0xcb, 0x07, 0x63, 0x36, 0x40, 0x9b, 0xce, 0xd9, 0x09, 0xb8, 0x11, 0xbe, 0x87, 0xa9,
|
||||
0x66, 0x85, 0x21, 0xeb, 0x11, 0x4c, 0x23, 0xd6, 0x07, 0x68, 0xaf, 0xe9, 0x65, 0x63, 0xc8, 0x7a,
|
||||
0xa0, 0xd2, 0x88, 0xf5, 0x09, 0x64, 0x23, 0xfc, 0x00, 0x57, 0x66, 0x59, 0x18, 0xb1, 0xfe, 0xaa,
|
||||
0xd3, 0x98, 0x0d, 0x76, 0x98, 0x8d, 0x6e, 0xbc, 0xdf, 0xbe, 0x79, 0xed, 0xb7, 0xff, 0x02, 0x00,
|
||||
0x00, 0xff, 0xff, 0xea, 0xa0, 0x1e, 0x8e, 0x23, 0x04, 0x00, 0x00,
|
||||
var fileDescriptor_e67338fe1f659d14 = []byte{
|
||||
// 434 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xcd, 0x8e, 0xd3, 0x30,
|
||||
0x10, 0xc7, 0x9b, 0xb6, 0x1b, 0xe8, 0xb4, 0x49, 0xd1, 0x1c, 0x50, 0x14, 0x21, 0x51, 0x59, 0x42,
|
||||
0x2a, 0x20, 0xb9, 0xab, 0xf2, 0x00, 0x20, 0x95, 0x23, 0xa7, 0x20, 0xb4, 0x67, 0xe3, 0xce, 0x6e,
|
||||
0x23, 0x36, 0x1f, 0xc4, 0xce, 0xbe, 0xc3, 0xbe, 0x35, 0xf2, 0x47, 0x36, 0x49, 0x0f, 0x95, 0xca,
|
||||
0xcd, 0xf3, 0xf5, 0x9f, 0xb1, 0x7f, 0x93, 0xc0, 0x47, 0x59, 0x95, 0xf7, 0xf9, 0xc3, 0x4e, 0x55,
|
||||
0x6d, 0x23, 0x69, 0xa7, 0xa8, 0x79, 0xca, 0x25, 0xed, 0xea, 0xa6, 0xd2, 0x55, 0x67, 0x71, 0x6b,
|
||||
0xb1, 0xe7, 0x00, 0x16, 0x87, 0x93, 0x28, 0x1f, 0xe8, 0x27, 0x69, 0x44, 0x98, 0x1f, 0x85, 0x16,
|
||||
0x49, 0xb0, 0x09, 0xb6, 0x8b, 0xcc, 0x9e, 0x31, 0x85, 0xd7, 0xf2, 0x44, 0xf2, 0x8f, 0x6a, 0x8b,
|
||||
0x64, 0x6a, 0xfd, 0x2f, 0x36, 0xbe, 0x85, 0xf0, 0xbe, 0x6a, 0x0a, 0xa1, 0x93, 0x99, 0x8d, 0x78,
|
||||
0xcb, 0xf8, 0x5d, 0xef, 0x64, 0xee, 0xfc, 0xce, 0xc2, 0x77, 0xb0, 0xd0, 0x79, 0x41, 0x4a, 0x8b,
|
||||
0xa2, 0x4e, 0x6e, 0x36, 0xc1, 0x76, 0x96, 0xf5, 0x0e, 0x76, 0x84, 0xd0, 0x8d, 0x62, 0xf2, 0x4a,
|
||||
0x51, 0x90, 0xaa, 0x85, 0x24, 0x3f, 0x4c, 0xef, 0x30, 0x53, 0xd6, 0x42, 0x9f, 0xfc, 0x34, 0xf6,
|
||||
0x8c, 0x5b, 0x58, 0xc8, 0xee, 0x1a, 0x76, 0x98, 0xe5, 0x1e, 0xf8, 0xcb, 0xc5, 0xb2, 0x3e, 0xc8,
|
||||
0x6e, 0x21, 0x3a, 0x34, 0x24, 0x34, 0x65, 0xf4, 0xb7, 0x25, 0xa5, 0xf1, 0x3d, 0x84, 0x2e, 0x6a,
|
||||
0x3b, 0x2d, 0xf7, 0xaf, 0x7c, 0x5d, 0xe6, 0xdd, 0xec, 0x0d, 0xc4, 0x5d, 0x85, 0xaa, 0xab, 0x52,
|
||||
0x91, 0xd1, 0xf8, 0x55, 0x1f, 0xaf, 0xd4, 0xe8, 0x2a, 0x7a, 0x8d, 0xef, 0xf4, 0x48, 0xd7, 0x69,
|
||||
0x74, 0x15, 0x5e, 0x23, 0x82, 0xe5, 0x8f, 0x5c, 0x69, 0xaf, 0xc0, 0x76, 0xb0, 0x72, 0xa6, 0x0b,
|
||||
0x1b, 0xc5, 0x27, 0xf1, 0xd8, 0x92, 0x4a, 0x82, 0xcd, 0x6c, 0xa4, 0xe8, 0xdc, 0xec, 0x2b, 0x2c,
|
||||
0x33, 0x12, 0xc7, 0x6e, 0x82, 0xab, 0x9f, 0xdd, 0x74, 0x74, 0x02, 0x7d, 0xc7, 0xcb, 0x77, 0xf8,
|
||||
0x06, 0xab, 0x3b, 0xa1, 0xe5, 0xe9, 0xff, 0x5b, 0xde, 0x41, 0xe4, 0x15, 0x7c, 0xcf, 0xcb, 0x12,
|
||||
0xa3, 0xc5, 0x98, 0x5e, 0x58, 0x8c, 0xfd, 0xf3, 0x14, 0xc2, 0x83, 0xfd, 0x70, 0xf0, 0x33, 0x84,
|
||||
0x8e, 0x38, 0xc6, 0x7c, 0xb4, 0x2c, 0xe9, 0x9a, 0x9f, 0xad, 0xc2, 0xc4, 0x24, 0x3b, 0xb4, 0x18,
|
||||
0xf3, 0xd1, 0x56, 0xa4, 0x6b, 0x7e, 0xc6, 0xdc, 0x26, 0x3b, 0x86, 0x18, 0xf3, 0x11, 0xfe, 0x74,
|
||||
0xcd, 0xcf, 0xe0, 0x4e, 0xf0, 0x03, 0xcc, 0x0d, 0x4f, 0x5c, 0xf1, 0x01, 0xe5, 0x34, 0xe2, 0x43,
|
||||
0xc8, 0x2e, 0xcd, 0x40, 0xc0, 0x15, 0x1f, 0xc0, 0x4c, 0x23, 0x3e, 0x24, 0xc3, 0x26, 0xf8, 0x09,
|
||||
0x6e, 0xec, 0xc3, 0x61, 0xc4, 0x87, 0x08, 0xd2, 0x98, 0x8f, 0xde, 0x93, 0x4d, 0x6e, 0x83, 0xdf,
|
||||
0xa1, 0xfd, 0x3b, 0x7c, 0xf9, 0x17, 0x00, 0x00, 0xff, 0xff, 0x05, 0xbb, 0xfd, 0xc1, 0x4a, 0x04,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// ConfigClient is the client API for Config service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type ConfigClient interface {
|
||||
Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error)
|
||||
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error)
|
||||
Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
|
||||
List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
|
||||
Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error)
|
||||
Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Config_WatchClient, error)
|
||||
}
|
||||
|
||||
type configClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewConfigClient(cc *grpc.ClientConn) ConfigClient {
|
||||
return &configClient{cc}
|
||||
}
|
||||
|
||||
func (c *configClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) {
|
||||
out := new(CreateResponse)
|
||||
err := c.cc.Invoke(ctx, "/Config/Create", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) {
|
||||
out := new(UpdateResponse)
|
||||
err := c.cc.Invoke(ctx, "/Config/Update", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
|
||||
out := new(DeleteResponse)
|
||||
err := c.cc.Invoke(ctx, "/Config/Delete", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) {
|
||||
out := new(ListResponse)
|
||||
err := c.cc.Invoke(ctx, "/Config/List", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) {
|
||||
out := new(ReadResponse)
|
||||
err := c.cc.Invoke(ctx, "/Config/Read", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) Watch(ctx context.Context, in *WatchRequest, opts ...grpc.CallOption) (Config_WatchClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_Config_serviceDesc.Streams[0], "/Config/Watch", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &configWatchClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Config_WatchClient interface {
|
||||
Recv() (*WatchResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type configWatchClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *configWatchClient) Recv() (*WatchResponse, error) {
|
||||
m := new(WatchResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// ConfigServer is the server API for Config service.
|
||||
type ConfigServer interface {
|
||||
Create(context.Context, *CreateRequest) (*CreateResponse, error)
|
||||
Update(context.Context, *UpdateRequest) (*UpdateResponse, error)
|
||||
Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
|
||||
List(context.Context, *ListRequest) (*ListResponse, error)
|
||||
Read(context.Context, *ReadRequest) (*ReadResponse, error)
|
||||
Watch(*WatchRequest, Config_WatchServer) error
|
||||
}
|
||||
|
||||
// UnimplementedConfigServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedConfigServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedConfigServer) Create(ctx context.Context, req *CreateRequest) (*CreateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Create not implemented")
|
||||
}
|
||||
func (*UnimplementedConfigServer) Update(ctx context.Context, req *UpdateRequest) (*UpdateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
|
||||
}
|
||||
func (*UnimplementedConfigServer) Delete(ctx context.Context, req *DeleteRequest) (*DeleteResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
|
||||
}
|
||||
func (*UnimplementedConfigServer) List(ctx context.Context, req *ListRequest) (*ListResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
|
||||
}
|
||||
func (*UnimplementedConfigServer) Read(ctx context.Context, req *ReadRequest) (*ReadResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Read not implemented")
|
||||
}
|
||||
func (*UnimplementedConfigServer) Watch(req *WatchRequest, srv Config_WatchServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Watch not implemented")
|
||||
}
|
||||
|
||||
func RegisterConfigServer(s *grpc.Server, srv ConfigServer) {
|
||||
s.RegisterService(&_Config_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Config_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CreateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).Create(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Config/Create",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).Create(ctx, req.(*CreateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(UpdateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).Update(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Config/Update",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).Update(ctx, req.(*UpdateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).Delete(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Config/Delete",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).Delete(ctx, req.(*DeleteRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).List(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Config/List",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).List(ctx, req.(*ListRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReadRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).Read(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Config/Read",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).Read(ctx, req.(*ReadRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_Watch_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(WatchRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(ConfigServer).Watch(m, &configWatchServer{stream})
|
||||
}
|
||||
|
||||
type Config_WatchServer interface {
|
||||
Send(*WatchResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type configWatchServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *configWatchServer) Send(m *WatchResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
var _Config_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Config",
|
||||
HandlerType: (*ConfigServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Create",
|
||||
Handler: _Config_Create_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Update",
|
||||
Handler: _Config_Update_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Delete",
|
||||
Handler: _Config_Delete_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "List",
|
||||
Handler: _Config_List_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Read",
|
||||
Handler: _Config_Read_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Watch",
|
||||
Handler: _Config_Watch_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "config/source/service/proto/service.proto",
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: go-micro/config/source/service/proto/service.proto
|
||||
// source: config/source/service/proto/service.proto
|
||||
|
||||
package service
|
||||
|
||||
@@ -48,12 +48,6 @@ type configService struct {
|
||||
}
|
||||
|
||||
func NewConfigService(name string, c client.Client) ConfigService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "config"
|
||||
}
|
||||
return &configService{
|
||||
c: c,
|
||||
name: name,
|
||||
@@ -123,6 +117,7 @@ func (c *configService) Watch(ctx context.Context, in *WatchRequest, opts ...cli
|
||||
}
|
||||
|
||||
type Config_WatchService interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
Close() error
|
||||
@@ -137,6 +132,10 @@ func (x *configServiceWatch) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *configServiceWatch) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *configServiceWatch) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
@@ -214,6 +213,7 @@ func (h *configHandler) Watch(ctx context.Context, stream server.Stream) error {
|
||||
}
|
||||
|
||||
type Config_WatchStream interface {
|
||||
Context() context.Context
|
||||
SendMsg(interface{}) error
|
||||
RecvMsg(interface{}) error
|
||||
Close() error
|
||||
@@ -228,6 +228,10 @@ func (x *configWatchStream) Close() error {
|
||||
return x.stream.Close()
|
||||
}
|
||||
|
||||
func (x *configWatchStream) Context() context.Context {
|
||||
return x.stream.Context()
|
||||
}
|
||||
|
||||
func (x *configWatchStream) SendMsg(m interface{}) error {
|
||||
return x.stream.Send(m)
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ service Config {
|
||||
}
|
||||
|
||||
message ChangeSet {
|
||||
bytes data = 1;
|
||||
string data = 1;
|
||||
string checksum = 2;
|
||||
string format = 3;
|
||||
string source = 4;
|
||||
@@ -18,7 +18,7 @@ message ChangeSet {
|
||||
}
|
||||
|
||||
message Change {
|
||||
string key = 1;
|
||||
string namespace = 1;
|
||||
string path = 2;
|
||||
ChangeSet changeSet = 3;
|
||||
}
|
||||
@@ -48,7 +48,7 @@ message ListResponse {
|
||||
}
|
||||
|
||||
message ReadRequest {
|
||||
string key = 1;
|
||||
string namespace = 1;
|
||||
string path = 2;
|
||||
}
|
||||
|
||||
@@ -57,11 +57,11 @@ message ReadResponse {
|
||||
}
|
||||
|
||||
message WatchRequest {
|
||||
string key = 1;
|
||||
string namespace = 1;
|
||||
string path = 2;
|
||||
}
|
||||
|
||||
message WatchResponse {
|
||||
string key = 1;
|
||||
string namespace = 1;
|
||||
ChangeSet changeSet = 2;
|
||||
}
|
||||
|
@@ -6,26 +6,29 @@ import (
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/config/source"
|
||||
proto "github.com/micro/go-micro/v2/config/source/service/proto"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultName = "go.micro.config"
|
||||
DefaultKey = "NAMESPACE:CONFIG"
|
||||
DefaultPath = ""
|
||||
DefaultClient = client.DefaultClient
|
||||
DefaultName = "go.micro.config"
|
||||
DefaultNamespace = "global"
|
||||
DefaultPath = ""
|
||||
)
|
||||
|
||||
type service struct {
|
||||
serviceName string
|
||||
key string
|
||||
namespace string
|
||||
path string
|
||||
opts source.Options
|
||||
client proto.ConfigService
|
||||
}
|
||||
|
||||
func (m *service) Read() (set *source.ChangeSet, err error) {
|
||||
req, err := m.client.Read(context.Background(), &proto.ReadRequest{Key: m.key, Path: m.path})
|
||||
client := proto.NewConfigService(m.serviceName, client.DefaultClient)
|
||||
req, err := client.Read(context.Background(), &proto.ReadRequest{
|
||||
Namespace: m.namespace,
|
||||
Path: m.path,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -34,9 +37,15 @@ func (m *service) Read() (set *source.ChangeSet, err error) {
|
||||
}
|
||||
|
||||
func (m *service) Watch() (w source.Watcher, err error) {
|
||||
stream, err := m.client.Watch(context.Background(), &proto.WatchRequest{Key: m.key, Path: m.path})
|
||||
client := proto.NewConfigService(m.serviceName, client.DefaultClient)
|
||||
stream, err := client.Watch(context.Background(), &proto.WatchRequest{
|
||||
Namespace: m.namespace,
|
||||
Path: m.path,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("watch err: ", err)
|
||||
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
||||
logger.Error("watch err: ", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
return newWatcher(stream)
|
||||
@@ -58,7 +67,7 @@ func NewSource(opts ...source.Option) source.Source {
|
||||
}
|
||||
|
||||
addr := DefaultName
|
||||
key := DefaultKey
|
||||
namespace := DefaultNamespace
|
||||
path := DefaultPath
|
||||
|
||||
if options.Context != nil {
|
||||
@@ -67,9 +76,9 @@ func NewSource(opts ...source.Option) source.Source {
|
||||
addr = a
|
||||
}
|
||||
|
||||
k, ok := options.Context.Value(keyKey{}).(string)
|
||||
k, ok := options.Context.Value(namespaceKey{}).(string)
|
||||
if ok {
|
||||
key = k
|
||||
namespace = k
|
||||
}
|
||||
|
||||
p, ok := options.Context.Value(pathKey{}).(string)
|
||||
@@ -81,9 +90,8 @@ func NewSource(opts ...source.Option) source.Source {
|
||||
s := &service{
|
||||
serviceName: addr,
|
||||
opts: options,
|
||||
key: key,
|
||||
namespace: namespace,
|
||||
path: path,
|
||||
client: proto.NewConfigService(addr, DefaultClient),
|
||||
}
|
||||
|
||||
return s
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
func toChangeSet(c *proto.ChangeSet) *source.ChangeSet {
|
||||
return &source.ChangeSet{
|
||||
Data: c.Data,
|
||||
Data: []byte(c.Data),
|
||||
Checksum: c.Checksum,
|
||||
Format: c.Format,
|
||||
Timestamp: time.Unix(c.Timestamp, 0),
|
||||
|
@@ -10,6 +10,24 @@ type Profile interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
var (
|
||||
DefaultProfile Profile = new(noop)
|
||||
)
|
||||
|
||||
type noop struct{}
|
||||
|
||||
func (p *noop) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *noop) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *noop) String() string {
|
||||
return "noop"
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
// Name to use for the profile
|
||||
Name string
|
||||
|
@@ -1,11 +1,15 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: micro/go-micro/debug/service/proto/debug.proto
|
||||
// source: debug/service/proto/debug.proto
|
||||
|
||||
package debug
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
@@ -42,7 +46,7 @@ func (x SpanType) String() string {
|
||||
}
|
||||
|
||||
func (SpanType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{0}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{0}
|
||||
}
|
||||
|
||||
type HealthRequest struct {
|
||||
@@ -57,7 +61,7 @@ func (m *HealthRequest) Reset() { *m = HealthRequest{} }
|
||||
func (m *HealthRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*HealthRequest) ProtoMessage() {}
|
||||
func (*HealthRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{0}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{0}
|
||||
}
|
||||
|
||||
func (m *HealthRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -97,7 +101,7 @@ func (m *HealthResponse) Reset() { *m = HealthResponse{} }
|
||||
func (m *HealthResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*HealthResponse) ProtoMessage() {}
|
||||
func (*HealthResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{1}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{1}
|
||||
}
|
||||
|
||||
func (m *HealthResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -137,7 +141,7 @@ func (m *StatsRequest) Reset() { *m = StatsRequest{} }
|
||||
func (m *StatsRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*StatsRequest) ProtoMessage() {}
|
||||
func (*StatsRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{2}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{2}
|
||||
}
|
||||
|
||||
func (m *StatsRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -191,7 +195,7 @@ func (m *StatsResponse) Reset() { *m = StatsResponse{} }
|
||||
func (m *StatsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*StatsResponse) ProtoMessage() {}
|
||||
func (*StatsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{3}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{3}
|
||||
}
|
||||
|
||||
func (m *StatsResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -289,7 +293,7 @@ func (m *LogRequest) Reset() { *m = LogRequest{} }
|
||||
func (m *LogRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*LogRequest) ProtoMessage() {}
|
||||
func (*LogRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{4}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{4}
|
||||
}
|
||||
|
||||
func (m *LogRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -355,7 +359,7 @@ func (m *Record) Reset() { *m = Record{} }
|
||||
func (m *Record) String() string { return proto.CompactTextString(m) }
|
||||
func (*Record) ProtoMessage() {}
|
||||
func (*Record) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{5}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{5}
|
||||
}
|
||||
|
||||
func (m *Record) XXX_Unmarshal(b []byte) error {
|
||||
@@ -409,7 +413,7 @@ func (m *TraceRequest) Reset() { *m = TraceRequest{} }
|
||||
func (m *TraceRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*TraceRequest) ProtoMessage() {}
|
||||
func (*TraceRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{6}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{6}
|
||||
}
|
||||
|
||||
func (m *TraceRequest) XXX_Unmarshal(b []byte) error {
|
||||
@@ -448,7 +452,7 @@ func (m *TraceResponse) Reset() { *m = TraceResponse{} }
|
||||
func (m *TraceResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*TraceResponse) ProtoMessage() {}
|
||||
func (*TraceResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{7}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{7}
|
||||
}
|
||||
|
||||
func (m *TraceResponse) XXX_Unmarshal(b []byte) error {
|
||||
@@ -501,7 +505,7 @@ func (m *Span) Reset() { *m = Span{} }
|
||||
func (m *Span) String() string { return proto.CompactTextString(m) }
|
||||
func (*Span) ProtoMessage() {}
|
||||
func (*Span) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_dea322649cde1ef2, []int{8}
|
||||
return fileDescriptor_df91f41a5db378e6, []int{8}
|
||||
}
|
||||
|
||||
func (m *Span) XXX_Unmarshal(b []byte) error {
|
||||
@@ -593,48 +597,262 @@ func init() {
|
||||
proto.RegisterMapType((map[string]string)(nil), "Span.MetadataEntry")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("micro/go-micro/debug/service/proto/debug.proto", fileDescriptor_dea322649cde1ef2)
|
||||
func init() { proto.RegisterFile("debug/service/proto/debug.proto", fileDescriptor_df91f41a5db378e6) }
|
||||
|
||||
var fileDescriptor_df91f41a5db378e6 = []byte{
|
||||
// 594 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xdb, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0x8d, 0xed, 0x38, 0xb1, 0xa7, 0x8d, 0xa9, 0x96, 0x8b, 0x2c, 0x73, 0x69, 0x65, 0x09, 0x29,
|
||||
0x5c, 0xe4, 0x40, 0x79, 0x41, 0xf0, 0x86, 0x8a, 0x04, 0x52, 0x69, 0xa5, 0x6d, 0xfb, 0x01, 0x5b,
|
||||
0x7b, 0xe4, 0x1a, 0xea, 0x0b, 0xbb, 0xeb, 0x4a, 0xf9, 0x16, 0xbe, 0x80, 0x37, 0x7e, 0x86, 0xff,
|
||||
0x41, 0x7b, 0x71, 0x1b, 0x0b, 0xa1, 0x3e, 0xf0, 0xb6, 0xe7, 0xec, 0xec, 0xc9, 0xcc, 0xc9, 0xf1,
|
||||
0xc0, 0x6e, 0x81, 0xe7, 0x7d, 0xb9, 0x12, 0xc8, 0xaf, 0xaa, 0x1c, 0x57, 0x1d, 0x6f, 0x65, 0xbb,
|
||||
0xd2, 0x5c, 0xa6, 0xcf, 0xe9, 0x33, 0x58, 0x7c, 0x42, 0x76, 0x29, 0x2f, 0x28, 0x7e, 0xef, 0x51,
|
||||
0x48, 0x12, 0xc3, 0xdc, 0x56, 0xc7, 0xce, 0x9e, 0xb3, 0x0c, 0xe9, 0x00, 0xd3, 0x25, 0x44, 0x43,
|
||||
0xa9, 0xe8, 0xda, 0x46, 0x20, 0x79, 0x00, 0x33, 0x21, 0x99, 0xec, 0x85, 0x2d, 0xb5, 0x28, 0x5d,
|
||||
0xc2, 0xf6, 0x89, 0x64, 0x52, 0xdc, 0xae, 0xf9, 0xdb, 0x81, 0x85, 0x2d, 0xb5, 0x9a, 0x8f, 0x20,
|
||||
0x94, 0x55, 0x8d, 0x42, 0xb2, 0xba, 0xd3, 0xd5, 0x53, 0x7a, 0x43, 0x68, 0x25, 0xc9, 0xb8, 0xc4,
|
||||
0x22, 0x76, 0xf5, 0xdd, 0x00, 0x55, 0x2f, 0x7d, 0xa7, 0x0a, 0x63, 0x4f, 0x5f, 0x58, 0xa4, 0xf8,
|
||||
0x1a, 0xeb, 0x96, 0xaf, 0xe3, 0xa9, 0xe1, 0x0d, 0x52, 0x4a, 0xf2, 0x82, 0x23, 0x2b, 0x44, 0xec,
|
||||
0x1b, 0x25, 0x0b, 0x49, 0x04, 0x6e, 0x99, 0xc7, 0x33, 0x4d, 0xba, 0x65, 0x4e, 0x12, 0x08, 0xb8,
|
||||
0x19, 0x44, 0xc4, 0x73, 0xcd, 0x5e, 0x63, 0xa5, 0x8e, 0x9c, 0xb7, 0x5c, 0xc4, 0x81, 0x51, 0x37,
|
||||
0x28, 0xfd, 0x0a, 0x70, 0xd8, 0x96, 0xb7, 0xce, 0x6f, 0x1c, 0xe4, 0xc8, 0x6a, 0x3d, 0x4e, 0x40,
|
||||
0x2d, 0x22, 0xf7, 0xc0, 0xcf, 0xdb, 0xbe, 0x91, 0x7a, 0x18, 0x8f, 0x1a, 0xa0, 0x58, 0x51, 0x35,
|
||||
0x39, 0xea, 0x51, 0x3c, 0x6a, 0x40, 0xfa, 0xcb, 0x81, 0x19, 0xc5, 0xbc, 0xe5, 0xc5, 0xdf, 0xe6,
|
||||
0x79, 0x9b, 0xe6, 0xbd, 0x86, 0xa0, 0x46, 0xc9, 0x0a, 0x26, 0x59, 0xec, 0xee, 0x79, 0xcb, 0xad,
|
||||
0xfd, 0xfb, 0x99, 0x79, 0x98, 0x7d, 0xb1, 0xfc, 0xc7, 0x46, 0xf2, 0x35, 0xbd, 0x2e, 0x53, 0x9d,
|
||||
0xd7, 0x28, 0x04, 0x2b, 0x8d, 0xad, 0x21, 0x1d, 0x60, 0xf2, 0x1e, 0x16, 0xa3, 0x47, 0x64, 0x07,
|
||||
0xbc, 0x6f, 0xb8, 0xb6, 0x03, 0xaa, 0xa3, 0x6a, 0xf7, 0x8a, 0x5d, 0xf6, 0xa8, 0x67, 0x0b, 0xa9,
|
||||
0x01, 0xef, 0xdc, 0xb7, 0x4e, 0xfa, 0x04, 0xb6, 0x4f, 0x39, 0xcb, 0x71, 0x30, 0x28, 0x02, 0xb7,
|
||||
0x2a, 0xec, 0x53, 0xb7, 0x2a, 0xd2, 0x97, 0xb0, 0xb0, 0xf7, 0x36, 0x15, 0x0f, 0xc1, 0x17, 0x1d,
|
||||
0x6b, 0x54, 0xd0, 0x54, 0xdf, 0x7e, 0x76, 0xd2, 0xb1, 0x86, 0x1a, 0x2e, 0xfd, 0xe1, 0xc2, 0x54,
|
||||
0x61, 0xf5, 0x83, 0x52, 0x3d, 0xb3, 0x4a, 0x06, 0x58, 0x71, 0x77, 0x10, 0x57, 0x9e, 0x77, 0x8c,
|
||||
0xa3, 0x35, 0x37, 0xa4, 0x16, 0x11, 0x02, 0xd3, 0x86, 0xd5, 0xc6, 0xdc, 0x90, 0xea, 0xf3, 0x66,
|
||||
0xde, 0xfc, 0x71, 0xde, 0x12, 0x08, 0x8a, 0x9e, 0x33, 0x59, 0xb5, 0x8d, 0xcd, 0xca, 0x35, 0x26,
|
||||
0xab, 0x0d, 0xa3, 0xe7, 0xba, 0xe1, 0xbb, 0xba, 0xe1, 0x7f, 0xda, 0xfc, 0x18, 0xa6, 0x72, 0xdd,
|
||||
0xa1, 0x0e, 0x51, 0xb4, 0x1f, 0xea, 0xe2, 0xd3, 0x75, 0x87, 0x54, 0xd3, 0xff, 0xe5, 0xf5, 0xf3,
|
||||
0xa7, 0x10, 0x0c, 0x72, 0x64, 0x0b, 0xe6, 0x9f, 0x8f, 0x3e, 0x1c, 0x9f, 0x1d, 0x1d, 0xec, 0x4c,
|
||||
0xc8, 0x36, 0x04, 0xc7, 0x67, 0xa7, 0x06, 0x39, 0xfb, 0x3f, 0x1d, 0xf0, 0x0f, 0xd4, 0x62, 0x20,
|
||||
0xbb, 0xe0, 0x1d, 0xb6, 0x25, 0xd9, 0xca, 0x6e, 0x12, 0x9c, 0xcc, 0x6d, 0x50, 0xd2, 0xc9, 0x2b,
|
||||
0x87, 0xbc, 0x80, 0x99, 0x59, 0x04, 0x24, 0xca, 0x46, 0xcb, 0x23, 0xb9, 0x93, 0x8d, 0x37, 0x44,
|
||||
0x3a, 0x21, 0x4b, 0xf0, 0xf5, 0x07, 0x4e, 0x16, 0xd9, 0xe6, 0x4e, 0x48, 0xa2, 0x6c, 0xf4, 0xdd,
|
||||
0x9b, 0x4a, 0xfd, 0xa7, 0x93, 0x45, 0xb6, 0x19, 0x8e, 0x24, 0xca, 0x46, 0x59, 0x48, 0x27, 0xe7,
|
||||
0x33, 0xbd, 0xbb, 0xde, 0xfc, 0x09, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x42, 0x7f, 0x05, 0xde, 0x04,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
||||
var fileDescriptor_dea322649cde1ef2 = []byte{
|
||||
// 595 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0x5b, 0x6e, 0xd3, 0x40,
|
||||
0x14, 0x8d, 0x63, 0x3b, 0x71, 0x6e, 0x1e, 0x54, 0xc3, 0x43, 0x56, 0x78, 0xca, 0x12, 0x52, 0x78,
|
||||
0x39, 0x10, 0x7e, 0x10, 0xfc, 0xa1, 0x22, 0x81, 0x04, 0xad, 0x34, 0x4d, 0x17, 0x30, 0xb5, 0x47,
|
||||
0xa9, 0xa1, 0xf6, 0x98, 0x99, 0x71, 0xa5, 0xac, 0x85, 0x15, 0xf0, 0xc7, 0x66, 0xd8, 0x0f, 0xf3,
|
||||
0x72, 0x1a, 0x0b, 0xa1, 0x7e, 0xf0, 0x77, 0xcf, 0xf5, 0x99, 0x33, 0xf7, 0x9e, 0x9c, 0x0c, 0xa4,
|
||||
0x65, 0x91, 0x71, 0xb6, 0xdc, 0xb0, 0x17, 0xb6, 0xc8, 0xe9, 0x59, 0xb3, 0x59, 0x0a, 0xca, 0x2f,
|
||||
0x8b, 0x8c, 0x2e, 0x6b, 0xce, 0xa4, 0xeb, 0xa5, 0xa6, 0x4e, 0x9e, 0xc0, 0xf4, 0x23, 0x25, 0x17,
|
||||
0xf2, 0x1c, 0xd3, 0xef, 0x0d, 0x15, 0x12, 0xc5, 0x30, 0x74, 0xec, 0xd8, 0x7b, 0xe4, 0x2d, 0x46,
|
||||
0xb8, 0x85, 0xc9, 0x02, 0x66, 0x2d, 0x55, 0xd4, 0xac, 0x12, 0x14, 0xdd, 0x81, 0x81, 0x90, 0x44,
|
||||
0x36, 0xc2, 0x51, 0x1d, 0x52, 0xcc, 0xc9, 0x89, 0xaa, 0xc4, 0xf5, 0x9a, 0xbf, 0x3d, 0x98, 0x3a,
|
||||
0xaa, 0xd3, 0xbc, 0x07, 0x23, 0x59, 0x94, 0xea, 0x14, 0x29, 0x6b, 0xc3, 0x0e, 0xf0, 0x55, 0xc3,
|
||||
0x28, 0x49, 0xc2, 0x25, 0xcd, 0xe3, 0xbe, 0xf9, 0xd6, 0x42, 0x3d, 0x4b, 0x53, 0x6b, 0x62, 0xec,
|
||||
0x9b, 0x0f, 0x0e, 0xe9, 0x7e, 0x49, 0x4b, 0xc6, 0xb7, 0x71, 0x60, 0xfb, 0x16, 0x69, 0x25, 0x79,
|
||||
0xce, 0x29, 0xc9, 0x45, 0x1c, 0x5a, 0x25, 0x07, 0xd1, 0x0c, 0xfa, 0x9b, 0x2c, 0x1e, 0x98, 0xa6,
|
||||
0xaa, 0xd0, 0x1c, 0x22, 0x6e, 0x17, 0x11, 0xf1, 0xd0, 0x74, 0x77, 0x58, 0xab, 0x53, 0xce, 0x19,
|
||||
0x17, 0x71, 0x64, 0xd5, 0x2d, 0x4a, 0xbe, 0x02, 0x7c, 0x66, 0x9b, 0x6b, 0xf7, 0xb7, 0x0e, 0xaa,
|
||||
0x6b, 0x4b, 0xb3, 0x4e, 0x84, 0x1d, 0x42, 0xb7, 0x20, 0xcc, 0x58, 0x53, 0x49, 0xb3, 0x8c, 0x8f,
|
||||
0x2d, 0xd0, 0x5d, 0x51, 0x54, 0x4a, 0x25, 0xb0, 0x5d, 0x03, 0x92, 0x5f, 0x1e, 0x0c, 0x30, 0xcd,
|
||||
0x18, 0xcf, 0xff, 0x36, 0xcf, 0xdf, 0x37, 0xef, 0x15, 0x44, 0x25, 0x95, 0x24, 0x27, 0x92, 0xa8,
|
||||
0xeb, 0xfc, 0xc5, 0x78, 0x75, 0x3b, 0xb5, 0x07, 0xd3, 0x2f, 0xae, 0xff, 0xa1, 0x92, 0x7c, 0x8b,
|
||||
0x77, 0x34, 0x3d, 0xb9, 0x3a, 0x2d, 0xc8, 0xc6, 0xda, 0xaa, 0x26, 0x77, 0x70, 0xfe, 0x0e, 0xa6,
|
||||
0x9d, 0x43, 0xe8, 0x00, 0xfc, 0x6f, 0x74, 0xeb, 0x16, 0xd4, 0xa5, 0x1e, 0xf7, 0x92, 0x5c, 0x34,
|
||||
0xd4, 0xec, 0x36, 0xc2, 0x16, 0xbc, 0xed, 0xbf, 0xf1, 0x92, 0x07, 0x30, 0x59, 0x73, 0x92, 0xd1,
|
||||
0xd6, 0x20, 0x65, 0x79, 0x91, 0xbb, 0xa3, 0xaa, 0x4a, 0x9e, 0xc3, 0xd4, 0x7d, 0x77, 0xa9, 0xb8,
|
||||
0xab, 0x36, 0xaf, 0x49, 0xa5, 0x83, 0xa6, 0xe7, 0x0e, 0xd3, 0x13, 0x85, 0xb0, 0xed, 0x25, 0x3f,
|
||||
0xfa, 0x10, 0x68, 0xac, 0x2f, 0x94, 0xfa, 0x98, 0x53, 0xb2, 0xc0, 0x89, 0xf7, 0x5b, 0x71, 0xed,
|
||||
0x79, 0x4d, 0x38, 0x75, 0xe6, 0xaa, 0xd4, 0x5a, 0x84, 0x10, 0x04, 0x15, 0x29, 0xad, 0xb9, 0x23,
|
||||
0x6c, 0xea, 0xfd, 0xbc, 0x85, 0xdd, 0xbc, 0xa9, 0x54, 0xe4, 0x0d, 0x27, 0xb2, 0x60, 0x95, 0xcb,
|
||||
0xca, 0x0e, 0xa3, 0xe5, 0x9e, 0xd1, 0x43, 0x33, 0xf0, 0x4d, 0x33, 0xf0, 0x3f, 0x6d, 0xbe, 0x0f,
|
||||
0x81, 0xdc, 0xd6, 0xd4, 0x84, 0x68, 0xb6, 0x1a, 0x19, 0xf2, 0x5a, 0x35, 0xb0, 0x69, 0xff, 0x97,
|
||||
0xd7, 0x4f, 0x1f, 0x43, 0xd4, 0xca, 0xa1, 0x31, 0x0c, 0x3f, 0x1d, 0xbd, 0x3f, 0x3e, 0x3d, 0x3a,
|
||||
0x3c, 0xe8, 0xa1, 0x09, 0x44, 0xc7, 0xa7, 0x6b, 0x8b, 0xbc, 0xd5, 0x4f, 0x0f, 0xc2, 0x43, 0xfd,
|
||||
0x30, 0xa0, 0x87, 0xe0, 0xab, 0xec, 0xa2, 0x71, 0x7a, 0x95, 0xe0, 0xf9, 0xd0, 0x05, 0x25, 0xe9,
|
||||
0xbd, 0xf4, 0xd0, 0x33, 0x18, 0xd8, 0x87, 0x00, 0xcd, 0xd2, 0xce, 0xe3, 0x31, 0xbf, 0x91, 0x76,
|
||||
0x5f, 0x88, 0xa4, 0x87, 0x16, 0x10, 0x9a, 0x3f, 0x38, 0x9a, 0xa6, 0xfb, 0x6f, 0xc2, 0x7c, 0x96,
|
||||
0x76, 0xfe, 0xf7, 0x96, 0x69, 0x7e, 0x74, 0xc5, 0xdc, 0x0f, 0x87, 0x62, 0x76, 0xb2, 0x90, 0xf4,
|
||||
0xce, 0x06, 0xe6, 0xed, 0x7a, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0xbc, 0xab, 0x72, 0x03, 0xed,
|
||||
0x04, 0x00, 0x00,
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// DebugClient is the client API for Debug service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type DebugClient interface {
|
||||
Log(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (Debug_LogClient, error)
|
||||
Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error)
|
||||
Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error)
|
||||
Trace(ctx context.Context, in *TraceRequest, opts ...grpc.CallOption) (*TraceResponse, error)
|
||||
}
|
||||
|
||||
type debugClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewDebugClient(cc *grpc.ClientConn) DebugClient {
|
||||
return &debugClient{cc}
|
||||
}
|
||||
|
||||
func (c *debugClient) Log(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (Debug_LogClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_Debug_serviceDesc.Streams[0], "/Debug/Log", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &debugLogClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Debug_LogClient interface {
|
||||
Recv() (*Record, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type debugLogClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *debugLogClient) Recv() (*Record, error) {
|
||||
m := new(Record)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *debugClient) Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) {
|
||||
out := new(HealthResponse)
|
||||
err := c.cc.Invoke(ctx, "/Debug/Health", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *debugClient) Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error) {
|
||||
out := new(StatsResponse)
|
||||
err := c.cc.Invoke(ctx, "/Debug/Stats", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *debugClient) Trace(ctx context.Context, in *TraceRequest, opts ...grpc.CallOption) (*TraceResponse, error) {
|
||||
out := new(TraceResponse)
|
||||
err := c.cc.Invoke(ctx, "/Debug/Trace", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DebugServer is the server API for Debug service.
|
||||
type DebugServer interface {
|
||||
Log(*LogRequest, Debug_LogServer) error
|
||||
Health(context.Context, *HealthRequest) (*HealthResponse, error)
|
||||
Stats(context.Context, *StatsRequest) (*StatsResponse, error)
|
||||
Trace(context.Context, *TraceRequest) (*TraceResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedDebugServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedDebugServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedDebugServer) Log(req *LogRequest, srv Debug_LogServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Log not implemented")
|
||||
}
|
||||
func (*UnimplementedDebugServer) Health(ctx context.Context, req *HealthRequest) (*HealthResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Health not implemented")
|
||||
}
|
||||
func (*UnimplementedDebugServer) Stats(ctx context.Context, req *StatsRequest) (*StatsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Stats not implemented")
|
||||
}
|
||||
func (*UnimplementedDebugServer) Trace(ctx context.Context, req *TraceRequest) (*TraceResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Trace not implemented")
|
||||
}
|
||||
|
||||
func RegisterDebugServer(s *grpc.Server, srv DebugServer) {
|
||||
s.RegisterService(&_Debug_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Debug_Log_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(LogRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(DebugServer).Log(m, &debugLogServer{stream})
|
||||
}
|
||||
|
||||
type Debug_LogServer interface {
|
||||
Send(*Record) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type debugLogServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *debugLogServer) Send(m *Record) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _Debug_Health_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(HealthRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DebugServer).Health(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Debug/Health",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DebugServer).Health(ctx, req.(*HealthRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Debug_Stats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(StatsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DebugServer).Stats(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Debug/Stats",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DebugServer).Stats(ctx, req.(*StatsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Debug_Trace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TraceRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DebugServer).Trace(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Debug/Trace",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DebugServer).Trace(ctx, req.(*TraceRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Debug_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Debug",
|
||||
HandlerType: (*DebugServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Health",
|
||||
Handler: _Debug_Health_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Stats",
|
||||
Handler: _Debug_Stats_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Trace",
|
||||
Handler: _Debug_Trace_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Log",
|
||||
Handler: _Debug_Log_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "debug/service/proto/debug.proto",
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: micro/go-micro/debug/service/proto/debug.proto
|
||||
// source: debug/service/proto/debug.proto
|
||||
|
||||
package debug
|
||||
|
||||
|
@@ -115,3 +115,32 @@ func InternalServerError(id, format string, a ...interface{}) error {
|
||||
Status: http.StatusText(500),
|
||||
}
|
||||
}
|
||||
|
||||
// Equal tries to compare errors
|
||||
func Equal(err1 error, err2 error) bool {
|
||||
verr1, ok1 := err1.(*Error)
|
||||
verr2, ok2 := err2.(*Error)
|
||||
|
||||
if ok1 != ok2 {
|
||||
return false
|
||||
}
|
||||
|
||||
if !ok1 {
|
||||
return err1 == err2
|
||||
}
|
||||
|
||||
if verr1.Code != verr2.Code {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// FromError try to convert go error to *Error
|
||||
func FromError(err error) *Error {
|
||||
if verr, ok := err.(*Error); ok && verr != nil {
|
||||
return verr
|
||||
}
|
||||
|
||||
return Parse(err.Error())
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: errors.proto
|
||||
// source: errors/errors.proto
|
||||
|
||||
package errors
|
||||
|
||||
@@ -34,7 +34,7 @@ func (m *Error) Reset() { *m = Error{} }
|
||||
func (m *Error) String() string { return proto.CompactTextString(m) }
|
||||
func (*Error) ProtoMessage() {}
|
||||
func (*Error) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_24fe73c7f0ddb19c, []int{0}
|
||||
return fileDescriptor_85c4eef3398a32b2, []int{0}
|
||||
}
|
||||
|
||||
func (m *Error) XXX_Unmarshal(b []byte) error {
|
||||
@@ -87,16 +87,16 @@ func init() {
|
||||
proto.RegisterType((*Error)(nil), "errors.Error")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("errors.proto", fileDescriptor_24fe73c7f0ddb19c) }
|
||||
func init() { proto.RegisterFile("errors/errors.proto", fileDescriptor_85c4eef3398a32b2) }
|
||||
|
||||
var fileDescriptor_24fe73c7f0ddb19c = []byte{
|
||||
// 116 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x2d, 0x2a, 0xca,
|
||||
0x2f, 0x2a, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xf0, 0x94, 0xa2, 0xb9, 0x58,
|
||||
0x5d, 0x41, 0x2c, 0x21, 0x3e, 0x2e, 0xa6, 0xcc, 0x14, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20,
|
||||
0xa6, 0xcc, 0x14, 0x21, 0x21, 0x2e, 0x96, 0xe4, 0xfc, 0x94, 0x54, 0x09, 0x26, 0x05, 0x46, 0x0d,
|
||||
0xd6, 0x20, 0x30, 0x5b, 0x48, 0x8c, 0x8b, 0x2d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0x47, 0x82, 0x19,
|
||||
0xac, 0x0e, 0xca, 0x03, 0x89, 0x17, 0x97, 0x24, 0x96, 0x94, 0x16, 0x4b, 0xb0, 0x40, 0xc4, 0x21,
|
||||
0xbc, 0x24, 0x36, 0xb0, 0x5d, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xef, 0xe7, 0x5d, 0xd3,
|
||||
0x7b, 0x00, 0x00, 0x00,
|
||||
var fileDescriptor_85c4eef3398a32b2 = []byte{
|
||||
// 118 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0x2d, 0x2a, 0xca,
|
||||
0x2f, 0x2a, 0xd6, 0x87, 0x50, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x6c, 0x10, 0x9e, 0x52,
|
||||
0x34, 0x17, 0xab, 0x2b, 0x88, 0x25, 0xc4, 0xc7, 0xc5, 0x94, 0x99, 0x22, 0xc1, 0xa8, 0xc0, 0xa8,
|
||||
0xc1, 0x19, 0xc4, 0x94, 0x99, 0x22, 0x24, 0xc4, 0xc5, 0x92, 0x9c, 0x9f, 0x92, 0x2a, 0xc1, 0xa4,
|
||||
0xc0, 0xa8, 0xc1, 0x1a, 0x04, 0x66, 0x0b, 0x89, 0x71, 0xb1, 0xa5, 0xa4, 0x96, 0x24, 0x66, 0xe6,
|
||||
0x48, 0x30, 0x83, 0xd5, 0x41, 0x79, 0x20, 0xf1, 0xe2, 0x92, 0xc4, 0x92, 0xd2, 0x62, 0x09, 0x16,
|
||||
0x88, 0x38, 0x84, 0x97, 0xc4, 0x06, 0xb6, 0xcb, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xca, 0xc3,
|
||||
0xcb, 0x29, 0x82, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
21
errors/errors.pb.micro.go
Normal file
21
errors/errors.pb.micro.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: errors/errors.proto
|
||||
|
||||
package errors
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user