From ad5e9032a37fb6450446d60656fb34b7eb91f24d Mon Sep 17 00:00:00 2001 From: haiyux Date: Thu, 2 Jun 2022 19:05:01 +0800 Subject: [PATCH] feat: make secure url to grpcs://127.0.0.1/ (#2072) * feat:make secure url to grpcs://127.0.0.1/ --- internal/endpoint/endpoint.go | 38 ++++++++++--- internal/endpoint/endpoint_test.go | 57 ++++++++++++++----- transport/grpc/resolver/discovery/resolver.go | 2 +- transport/grpc/server.go | 2 +- transport/http/resolver.go | 2 +- transport/http/server.go | 5 +- 6 files changed, 79 insertions(+), 27 deletions(-) diff --git a/internal/endpoint/endpoint.go b/internal/endpoint/endpoint.go index a125d924f..e4c9ef969 100644 --- a/internal/endpoint/endpoint.go +++ b/internal/endpoint/endpoint.go @@ -6,29 +6,42 @@ import ( ) // NewEndpoint new an Endpoint URL. -func NewEndpoint(scheme, host string, isSecure bool) *url.URL { - var query string - if isSecure { - query = "isSecure=true" - } - return &url.URL{Scheme: scheme, Host: host, RawQuery: query} +func NewEndpoint(scheme, host string) *url.URL { + return &url.URL{Scheme: scheme, Host: host} } // ParseEndpoint parses an Endpoint URL. -func ParseEndpoint(endpoints []string, scheme string, isSecure bool) (string, error) { +func ParseEndpoint(endpoints []string, scheme string) (string, error) { for _, e := range endpoints { u, err := url.Parse(e) if err != nil { return "", err } - if u.Scheme == scheme && IsSecure(u) == isSecure { + + // TODO: Compatibility processing + // Function is to convert grpc:/127.0.0.1/?isSecure=true into grpcs:/127.0.0.1/ + // It will be deleted in about a month + u = legacyURLToNew(u) + if u.Scheme == scheme { return u.Host, nil } } return "", nil } +func legacyURLToNew(u *url.URL) *url.URL { + if u.Scheme == "https" || u.Scheme == "grpcs" { + return u + } + if IsSecure(u) { + return &url.URL{Scheme: u.Scheme + "s", Host: u.Host} + } + return u +} + // IsSecure parses isSecure for Endpoint URL. +// Note: It will be deleted after some time, +// unified use grpcs://127.0.0.1:8080 instead of grpc://127.0.0.1:8080?isSecure=true func IsSecure(u *url.URL) bool { ok, err := strconv.ParseBool(u.Query().Get("isSecure")) if err != nil { @@ -36,3 +49,12 @@ func IsSecure(u *url.URL) bool { } return ok } + +// Scheme is the scheme of endpoint url. +// examples: scheme="http",isSecure=true get "https" +func Scheme(scheme string, isSecure bool) string { + if isSecure { + return scheme + "s" + } + return scheme +} diff --git a/internal/endpoint/endpoint_test.go b/internal/endpoint/endpoint_test.go index db0892882..356d8fbcd 100644 --- a/internal/endpoint/endpoint_test.go +++ b/internal/endpoint/endpoint_test.go @@ -18,17 +18,17 @@ func TestEndPoint(t *testing.T) { // TODO: Add test cases. { name: "grpc://127.0.0.1?isSecure=false", - args: args{NewEndpoint("grpc", "127.0.0.1", false)}, + args: args{&url.URL{Scheme: "grpc", Host: "127.0.0.1", RawQuery: "isSecure=false"}}, want: false, }, { name: "grpc://127.0.0.1?isSecure=true", - args: args{NewEndpoint("http", "127.0.0.1", true)}, + args: args{&url.URL{Scheme: "grpc", Host: "127.0.0.1", RawQuery: "isSecure=true"}}, want: true, }, { name: "grpc://127.0.0.1", - args: args{NewEndpoint("grpc", "localhost", false)}, + args: args{&url.URL{Scheme: "grpc", Host: "127.0.0.1"}}, want: false, }, } @@ -43,9 +43,8 @@ func TestEndPoint(t *testing.T) { func TestNewEndpoint(t *testing.T) { type args struct { - scheme string - host string - isSecure bool + scheme string + host string } tests := []struct { name string @@ -54,18 +53,23 @@ func TestNewEndpoint(t *testing.T) { }{ { name: "https://github.com/go-kratos/kratos/", - args: args{"https", "github.com/go-kratos/kratos/", false}, + args: args{"https", "github.com/go-kratos/kratos/"}, want: &url.URL{Scheme: "https", Host: "github.com/go-kratos/kratos/"}, }, { name: "https://go-kratos.dev/", - args: args{"https", "go-kratos.dev/", true}, - want: &url.URL{Scheme: "https", Host: "go-kratos.dev/", RawQuery: "isSecure=true"}, + args: args{"https", "go-kratos.dev/"}, + want: &url.URL{Scheme: "https", Host: "go-kratos.dev/"}, + }, + { + name: "https://www.google.com/", + args: args{"https", "www.google.com/"}, + want: &url.URL{Scheme: "https", Host: "www.google.com/"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := NewEndpoint(tt.args.scheme, tt.args.host, tt.args.isSecure); !reflect.DeepEqual(got, tt.want) { + if got := NewEndpoint(tt.args.scheme, tt.args.host); !reflect.DeepEqual(got, tt.want) { t.Errorf("NewEndpoint() = %v, want %v", got, tt.want) } }) @@ -76,7 +80,6 @@ func TestParseEndpoint(t *testing.T) { type args struct { endpoints []string scheme string - isSecure bool } tests := []struct { name string @@ -86,20 +89,46 @@ func TestParseEndpoint(t *testing.T) { }{ { name: "kratos", - args: args{endpoints: []string{"https://github.com/go-kratos/kratos?isSecure=true"}, scheme: "https", isSecure: true}, + args: args{endpoints: []string{"https://github.com/go-kratos/kratos"}, scheme: "https"}, want: "github.com", wantErr: false, }, { name: "test", - args: args{endpoints: []string{"https://go-kratos.dev/"}, scheme: "http", isSecure: true}, + args: args{endpoints: []string{"http://go-kratos.dev/"}, scheme: "https"}, want: "", wantErr: false, }, + { + name: "localhost:8080", + args: args{endpoints: []string{"grpcs://localhost:8080/"}, scheme: "grpcs"}, + want: "localhost:8080", + wantErr: false, + }, + { + name: "localhost:8081", + args: args{endpoints: []string{"grpcs://localhost:8080/"}, scheme: "grpc"}, + want: "", + wantErr: false, + }, + + // Legacy + { + name: "google", + args: args{endpoints: []string{"grpc://www.google.com/?isSecure=true"}, scheme: "grpcs"}, + want: "www.google.com", + wantErr: false, + }, + { + name: "baidu", + args: args{endpoints: []string{"http://www.baidu.com/?isSecure=true"}, scheme: "https"}, + want: "www.baidu.com", + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := ParseEndpoint(tt.args.endpoints, tt.args.scheme, tt.args.isSecure) + got, err := ParseEndpoint(tt.args.endpoints, tt.args.scheme) if (err != nil) != tt.wantErr { t.Errorf("ParseEndpoint() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/transport/grpc/resolver/discovery/resolver.go b/transport/grpc/resolver/discovery/resolver.go index 770fa8013..6a7f6e7e8 100644 --- a/transport/grpc/resolver/discovery/resolver.go +++ b/transport/grpc/resolver/discovery/resolver.go @@ -49,7 +49,7 @@ func (r *discoveryResolver) update(ins []*registry.ServiceInstance) { addrs := make([]resolver.Address, 0) endpoints := make(map[string]struct{}) for _, in := range ins { - endpoint, err := endpoint.ParseEndpoint(in.Endpoints, "grpc", !r.insecure) + endpoint, err := endpoint.ParseEndpoint(in.Endpoints, endpoint.Scheme("grpc", !r.insecure)) if err != nil { log.Errorf("[resolver] Failed to parse discovery endpoint: %v", err) continue diff --git a/transport/grpc/server.go b/transport/grpc/server.go index 8ec76884a..31c03f75e 100644 --- a/transport/grpc/server.go +++ b/transport/grpc/server.go @@ -207,6 +207,6 @@ func (s *Server) listenAndEndpoint() error { _ = s.lis.Close() return err } - s.endpoint = endpoint.NewEndpoint("grpc", addr, s.tlsConf != nil) + s.endpoint = endpoint.NewEndpoint(endpoint.Scheme("grpc", s.tlsConf != nil), addr) return nil } diff --git a/transport/http/resolver.go b/transport/http/resolver.go index 1a4ba81c5..f742c36a8 100644 --- a/transport/http/resolver.go +++ b/transport/http/resolver.go @@ -112,7 +112,7 @@ func newResolver(ctx context.Context, discovery registry.Discovery, target *Targ func (r *resolver) update(services []*registry.ServiceInstance) bool { nodes := make([]selector.Node, 0) for _, ins := range services { - ept, err := endpoint.ParseEndpoint(ins.Endpoints, "http", !r.insecure) + ept, err := endpoint.ParseEndpoint(ins.Endpoints, endpoint.Scheme("http", !r.insecure)) if err != nil { log.Errorf("Failed to parse (%v) discovery endpoint: %v error %v", r.target, ins.Endpoints, err) continue diff --git a/transport/http/server.go b/transport/http/server.go index 58f3060de..c45a72697 100644 --- a/transport/http/server.go +++ b/transport/http/server.go @@ -224,7 +224,8 @@ func (s *Server) filter() mux.MiddlewareFunc { // Endpoint return a real address to registry endpoint. // examples: -// http://127.0.0.1:8000?isSecure=false +// https://127.0.0.1:8000 +// Legacy: http://127.0.0.1:8000?isSecure=false func (s *Server) Endpoint() (*url.URL, error) { if s.err != nil { return nil, s.err @@ -272,6 +273,6 @@ func (s *Server) listenAndEndpoint() error { _ = s.lis.Close() return err } - s.endpoint = endpoint.NewEndpoint("http", addr, s.tlsConf != nil) + s.endpoint = endpoint.NewEndpoint(endpoint.Scheme("http", s.tlsConf != nil), addr) return nil }