nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: go-kratos/kratos
Pull request #772 (2021-03-16 11:09:11)

log: add log verbose


Patch:
diff --git a/log/verbose.go b/log/verbose.go
new file mode 100644
index 00000000..f2f44e83
--- /dev/null
+++ b/log/verbose.go
@@ -0,0 +1,30 @@
+package log
+
+// Verbose is a verbose type that implements Logger Print.
+type Verbose struct {
+	log     Logger
+	level   Level
+	enabled bool
+}
+
+// NewVerbose new a verbose with level.
+func NewVerbose(log Logger, level Level) Verbose {
+	return Verbose{log: log, level: level}
+}
+
+// Enabled will return true if this log level is enabled, guarded by the value of v.
+func (v Verbose) Enabled(level Level) bool {
+	return v.level <= level
+}
+
+// V reports whether verbosity at the call site is at least the requested level.
+func (v Verbose) V(level Level) Verbose {
+	return Verbose{log: v.log, enabled: v.Enabled(level)}
+}
+
+// Print is equivalent to the Print function, guarded by the value of v.
+func (v Verbose) Print(a ...interface{}) {
+	if v.enabled {
+		v.log.Print(a...)
+	}
+}


Test patch:
diff --git a/log/verbose_test.go b/log/verbose_test.go
new file mode 100644
index 00000000..06ac3815
--- /dev/null
+++ b/log/verbose_test.go
@@ -0,0 +1,11 @@
+package log
+
+import "testing"
+
+func TestVerbose(t *testing.T) {
+	v := NewVerbose(DefaultLogger, 20)
+
+	v.V(10).Print("foo", "bar1")
+	v.V(20).Print("foo", "bar2")
+	v.V(30).Print("foo", "bar3")
+}
Repository: go-kratos/kratos
Pull request #817 (2021-04-08 09:06:37)

host: optimize isPrivateIP


Patch:
diff --git a/internal/host/host.go b/internal/host/host.go
index 383c812c..7ab5823d 100644
--- a/internal/host/host.go
+++ b/internal/host/host.go
@@ -5,20 +5,24 @@ import (
 	"strconv"
 )
 
-var (
-	privateAddrs = []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "fd00::/8"}
-)
-
 func isPrivateIP(addr string) bool {
-	ipAddr := net.ParseIP(addr)
-	for _, privateAddr := range privateAddrs {
-		if _, priv, err := net.ParseCIDR(privateAddr); err == nil {
-			if priv.Contains(ipAddr) {
-				return true
-			}
-		}
+	ip := net.ParseIP(addr)
+	if ip4 := ip.To4(); ip4 != nil {
+		// Following RFC 4193, Section 3. Local IPv6 Unicast Addresses which says:
+		//   The Internet Assigned Numbers Authority (IANA) has reserved the
+		//   following three blocks of the IPv4 address space for private internets:
+		//     10.0.0.0        -   10.255.255.255  (10/8 prefix)
+		//     172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
+		//     192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
+		return ip4[0] == 10 ||
+			(ip4[0] == 172 && ip4[1]&0xf0 == 16) ||
+			(ip4[0] == 192 && ip4[1] == 168)
 	}
-	return false
+	// Following RFC 4193, Section 3. Private Address Space which says:
+	//   The Internet Assigned Numbers Authority (IANA) has reserved the
+	//   following block of the IPv6 address space for local internets:
+	//     FC00::  -  FDFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF (FC00::/7 prefix)
+	return len(ip) == net.IPv6len && ip[0]&0xfe == 0xfc
 }
 
 // Port return a real port.
@@ -30,8 +34,8 @@ func Port(lis net.Listener) (int, bool) {
 }
 
 // Extract returns a private addr and port.
-func Extract(hostport string, lis net.Listener) (string, error) {
-	addr, port, err := net.SplitHostPort(hostport)
+func Extract(hostPort string, lis net.Listener) (string, error) {
+	addr, port, err := net.SplitHostPort(hostPort)
 	if err != nil {
 		return "", err
 	}


Test patch:
diff --git a/internal/host/host_test.go b/internal/host/host_test.go
index 900f3ad0..bc7fdfb5 100644
--- a/internal/host/host_test.go
+++ b/internal/host/host_test.go
@@ -14,6 +14,27 @@ func TestPrivateIP(t *testing.T) {
 		{"172.16.0.1", true},
 		{"192.168.1.1", true},
 		{"8.8.8.8", false},
+		{"1.1.1.1", false},
+		{"9.255.255.255", false},
+		{"10.0.0.0", true},
+		{"10.255.255.255", true},
+		{"11.0.0.0", false},
+		{"172.15.255.255", false},
+		{"172.16.0.0", true},
+		{"172.16.255.255", true},
+		{"172.23.18.255", true},
+		{"172.31.255.255", true},
+		{"172.31.0.0", true},
+		{"172.32.0.0", false},
+		{"192.167.255.255", false},
+		{"192.168.0.0", true},
+		{"192.168.255.255", true},
+		{"192.169.0.0", false},
+		{"fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", false},
+		{"fc00::", true},
+		{"fcff:1200:0:44::", true},
+		{"fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", true},
+		{"fe00::", false},
 	}
 	for _, test := range tests {
 		t.Run(test.addr, func(t *testing.T) {
Repository: go-kratos/kratos
Pull request #881 (2021-04-29 02:51:43)

api/errors: fix parse error


Patch:
diff --git a/errors/errors.go b/errors/errors.go
index 1fdb44ac..cec7fbf4 100644
--- a/errors/errors.go
+++ b/errors/errors.go
@@ -3,7 +3,6 @@ package errors
 import (
 	"errors"
 	"fmt"
-	"net/http"
 
 	"google.golang.org/genproto/googleapis/rpc/errdetails"
 	"google.golang.org/grpc/codes"
@@ -26,7 +25,7 @@ type Error struct {
 }
 
 func (e *Error) Error() string {
-	return fmt.Sprintf("error: domain = %s reason = %s", e.Domain, e.Reason)
+	return fmt.Sprintf("error: domain = %s reason = %s metadata = %v", e.Domain, e.Reason, e.Metadata)
 }
 
 // GRPCStatus returns the Status represented by se.
@@ -84,19 +83,19 @@ func Errorf(code codes.Code, domain, reason, format string, a ...interface{}) er
 // It supports wrapped errors.
 func Code(err error) codes.Code {
 	if err == nil {
-		return http.StatusOK
+		return codes.OK
 	}
-	if target := new(Error); errors.As(err, &target) {
-		return target.s.Code()
+	if se := FromError(err); err != nil {
+		return se.s.Code()
 	}
-	return http.StatusInternalServerError
+	return codes.Unknown
 }
 
 // Domain returns the domain for a particular error.
 // It supports wrapped errors.
 func Domain(err error) string {
-	if target := new(Error); errors.As(err, &target) {
-		return target.Domain
+	if se := FromError(err); err != nil {
+		return se.Domain
 	}
 	return ""
 }
@@ -104,8 +103,34 @@ func Domain(err error) string {
 // Reason returns the reason for a particular error.
 // It supports wrapped errors.
 func Reason(err error) string {
-	if target := new(Error); errors.As(err, &target) {
-		return target.Reason
+	if se := FromError(err); err != nil {
+		return se.Reason
 	}
 	return ""
 }
+
+// FromError try to convert an error to *Error.
+// It supports wrapped errors.
+func FromError(err error) *Error {
+	if err == nil {
+		return nil
+	}
+	if target := new(Error); errors.As(err, &target) {
+		return target
+	}
+	gs, ok := status.FromError(err)
+	if ok {
+		for _, detail := range gs.Details() {
+			switch d := detail.(type) {
+			case *errdetails.ErrorInfo:
+				return New(
+					gs.Code(),
+					d.Domain,
+					d.Reason,
+					gs.Message(),
+				).WithMetadata(d.Metadata)
+			}
+		}
+	}
+	return New(gs.Code(), "", "", err.Error())
+}


Test patch:
diff --git a/errors/errors_test.go b/errors/errors_test.go
index 3255a683..5031f190 100644
--- a/errors/errors_test.go
+++ b/errors/errors_test.go
@@ -46,4 +46,10 @@ func TestError(t *testing.T) {
 	if err3.Metadata["foo"] != "bar" {
 		t.Error("not expected metadata")
 	}
+
+	gs := err.GRPCStatus()
+	se := FromError(gs.Err())
+	if se.Domain != err.Domain || se.Reason != se.Reason {
+		t.Errorf("got %+v want %+v", se, err)
+	}
 }
Repository: go-kratos/kratos
Pull request #1068 (2021-06-16 08:57:37)

fix error decode


Patch:
diff --git a/transport/http/client.go b/transport/http/client.go
index 9eb84c51..a21557e9 100644
--- a/transport/http/client.go
+++ b/transport/http/client.go
@@ -298,6 +298,7 @@ func DefaultErrorDecoder(ctx context.Context, res *http.Response) error {
 	if err == nil {
 		e := new(errors.Error)
 		if err = CodecForResponse(res).Unmarshal(data, e); err == nil {
+			e.Code = int32(res.StatusCode)
 			return e
 		}
 	}


Test patch:
diff --git a/transport/http/client_test.go b/transport/http/client_test.go
index 30e4ba3b..22b5d835 100644
--- a/transport/http/client_test.go
+++ b/transport/http/client_test.go
@@ -4,12 +4,13 @@ import (
 	"bytes"
 	"context"
 	"encoding/json"
-	"github.com/go-kratos/kratos/v2/errors"
 	"io/ioutil"
 	nethttp "net/http"
 	"testing"
 	"time"
 
+	"github.com/go-kratos/kratos/v2/errors"
+
 	"github.com/stretchr/testify/assert"
 
 	"github.com/go-kratos/kratos/v2/registry"
@@ -161,7 +162,7 @@ func TestDefaultErrorDecoder(t *testing.T) {
 	}
 	err2 := DefaultErrorDecoder(context.TODO(), resp2)
 	assert.Error(t, err2)
-	assert.Equal(t, int32(54321), err2.(*errors.Error).GetCode())
+	assert.Equal(t, int32(500), err2.(*errors.Error).GetCode())
 	assert.Equal(t, "hi", err2.(*errors.Error).GetMessage())
 	assert.Equal(t, "FOO", err2.(*errors.Error).GetReason())
 }
Repository: go-kratos/kratos
Pull request #1080 (2021-06-18 16:58:08)

transport/http: fix cors filter


Patch:
diff --git a/transport/http/server.go b/transport/http/server.go
index f8cc7b35..709fe4c7 100644
--- a/transport/http/server.go
+++ b/transport/http/server.go
@@ -121,7 +121,9 @@ func NewServer(opts ...ServerOption) *Server {
 	for _, o := range opts {
 		o(srv)
 	}
-	srv.Server = &http.Server{Handler: srv}
+	srv.Server = &http.Server{
+		Handler: FilterChain(srv.filters...)(srv),
+	}
 	srv.router = mux.NewRouter()
 	srv.router.Use(srv.filter())
 	return srv
@@ -154,7 +156,6 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
 
 func (s *Server) filter() mux.MiddlewareFunc {
 	return func(next http.Handler) http.Handler {
-		next = FilterChain(s.filters...)(next)
 		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 			ctx, cancel := ic.Merge(req.Context(), s.ctx)
 			defer cancel()


Test patch:
diff --git a/transport/http/route_test.go b/transport/http/route_test.go
index c9046c4f..074df92e 100644
--- a/transport/http/route_test.go
+++ b/transport/http/route_test.go
@@ -17,6 +17,17 @@ type User struct {
 	Name string `json:"name"`
 }
 
+func corsFilter(next http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.Method == http.MethodOptions {
+			log.Println("cors:", r.Method, r.RequestURI)
+			w.Header().Set("Access-Control-Allow-Methods", r.Method)
+			return
+		}
+		next.ServeHTTP(w, r)
+	})
+}
+
 func authFilter(next http.Handler) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		// Do stuff here
@@ -37,7 +48,7 @@ func loggingFilter(next http.Handler) http.Handler {
 func TestRoute(t *testing.T) {
 	ctx := context.Background()
 	srv := NewServer(
-		Filter(loggingFilter),
+		Filter(corsFilter, loggingFilter),
 	)
 	route := srv.Route("/v1")
 	route.GET("/users/{name}", func(ctx Context) error {
@@ -141,4 +152,17 @@ func testRoute(t *testing.T, srv *Server) {
 	if u.Name != "bar" {
 		t.Fatalf("got %s want bar", u.Name)
 	}
+	// OPTIONS
+	req, _ = http.NewRequest("OPTIONS", base+"/users", nil)
+	resp, err = http.DefaultClient.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != 200 {
+		t.Fatalf("code: %d", resp.StatusCode)
+	}
+	if resp.Header.Get("Access-Control-Allow-Methods") != "OPTIONS" {
+		t.Fatal("cors failed")
+	}
 }
Repository: go-kratos/kratos
Pull request #1115 (2021-06-27 09:43:55)

add http ip port support


Patch:
diff --git a/internal/host/host.go b/internal/host/host.go
index 193056d6..dd7c23e7 100644
--- a/internal/host/host.go
+++ b/internal/host/host.go
@@ -6,6 +6,22 @@ import (
 	"strconv"
 )
 
+// ExtractHostPort from address
+func ExtractHostPort(addr string) (host string, port uint64, err error) {
+	var (
+		ports string
+	)
+	host, ports, err = net.SplitHostPort(addr)
+	if err != nil {
+		return
+	}
+	port, err = strconv.ParseUint(ports, 10, 16)
+	if err != nil {
+		return
+	}
+	return
+}
+
 func isValidIP(addr string) bool {
 	ip := net.ParseIP(addr)
 	return ip.IsGlobalUnicast() && !ip.IsInterfaceLocalMulticast()
diff --git a/transport/http/client.go b/transport/http/client.go
index 8eb42476..e41ae3d3 100644
--- a/transport/http/client.go
+++ b/transport/http/client.go
@@ -11,6 +11,7 @@ import (
 
 	"github.com/go-kratos/kratos/v2/encoding"
 	"github.com/go-kratos/kratos/v2/errors"
+	"github.com/go-kratos/kratos/v2/internal/host"
 	"github.com/go-kratos/kratos/v2/internal/httputil"
 	"github.com/go-kratos/kratos/v2/middleware"
 	"github.com/go-kratos/kratos/v2/registry"
@@ -150,7 +151,7 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) {
 			if r, err = newResolver(ctx, options.discovery, target, options.balancer); err != nil {
 				return nil, fmt.Errorf("[http client] new resolver failed!err: %v", options.endpoint)
 			}
-		} else {
+		} else if _, _, err := host.ExtractHostPort(options.endpoint); err != nil {
 			return nil, fmt.Errorf("[http client] invalid endpoint format: %v", options.endpoint)
 		}
 	}


Test patch:
diff --git a/internal/host/host_test.go b/internal/host/host_test.go
index 36d6548b..930e8c3e 100644
--- a/internal/host/host_test.go
+++ b/internal/host/host_test.go
@@ -86,3 +86,22 @@ func TestPort(t *testing.T) {
 		t.Fatalf("expected: %s got %d", lis.Addr().String(), port)
 	}
 }
+
+func TestExtractHostPort(t *testing.T) {
+	host, port, err := ExtractHostPort("127.0.0.1:8000")
+	if err != nil {
+		t.Fatalf("expected: %v got %v", nil, err)
+	}
+	t.Logf("host port: %s,  %d", host, port)
+
+	host, port, err = ExtractHostPort("www.bilibili.com:80")
+	if err != nil {
+		t.Fatalf("expected: %v got %v", nil, err)
+	}
+	t.Logf("host port: %s,  %d", host, port)
+
+	host, port, err = ExtractHostPort("consul://2/33")
+	if err == nil {
+		t.Fatalf("expected: not nil got %v", nil)
+	}
+}
Repository: go-kratos/kratos
Pull request #1232 (2021-07-23 09:15:58)

chore(config/env): minor refactor
提取 `load(envStrings []string)` 方法以便单元测试

Merge 时请合并提交历史

Windfarer: 测试里可以用github.com/stretchr/testify/assert包来判断相等吗？尽量避免引入新的依赖？
xuyang2: @Windfarer 换成 `reflect.DeepEqual` 了

Patch:
diff --git a/config/env/env.go b/config/env/env.go
index adf37c98..f8da4110 100644
--- a/config/env/env.go
+++ b/config/env/env.go
@@ -16,7 +16,12 @@ func NewSource(prefixs ...string) config.Source {
 }
 
 func (e *env) Load() (kv []*config.KeyValue, err error) {
-	for _, envstr := range os.Environ() {
+	return e.load(os.Environ()), nil
+}
+
+func (e *env) load(envStrings []string) []*config.KeyValue {
+	var kv []*config.KeyValue
+	for _, envstr := range envStrings {
 		var k, v string
 		subs := strings.SplitN(envstr, "=", 2)
 		k = subs[0]
@@ -41,7 +46,7 @@ func (e *env) Load() (kv []*config.KeyValue, err error) {
 			Value: []byte(v),
 		})
 	}
-	return
+	return kv
 }
 
 func (e *env) Watch() (config.Watcher, error) {


Test patch:
diff --git a/config/env/env_test.go b/config/env/env_test.go
index db5ec6d5..87f6def7 100644
--- a/config/env/env_test.go
+++ b/config/env/env_test.go
@@ -245,3 +245,67 @@ func TestEnvWithoutPrefix(t *testing.T) {
 		})
 	}
 }
+
+func Test_env_load(t *testing.T) {
+	type fields struct {
+		prefixs []string
+	}
+	type args struct {
+		envStrings []string
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   []*config.KeyValue
+	}{
+		{
+			name: "without prefixes",
+			fields: fields{
+				prefixs: nil,
+			},
+			args: args{
+				envStrings: []string{
+					"SERVICE_NAME=kratos_app",
+					"ADDR=192.168.0.1",
+					"AGE=20",
+				},
+			},
+			want: []*config.KeyValue{
+				{Key: "SERVICE_NAME", Value: []byte("kratos_app"), Format: ""},
+				{Key: "ADDR", Value: []byte("192.168.0.1"), Format: ""},
+				{Key: "AGE", Value: []byte("20"), Format: ""},
+			},
+		},
+
+		{
+			name: "with prefixes",
+			fields: fields{
+				prefixs: []string{"KRATOS_", "FOO"},
+			},
+			args: args{
+				envStrings: []string{
+					"KRATOS_SERVICE_NAME=kratos_app",
+					"KRATOS_ADDR=192.168.0.1",
+					"FOO_AGE=20",
+				},
+			},
+			want: []*config.KeyValue{
+				{Key: "SERVICE_NAME", Value: []byte("kratos_app"), Format: ""},
+				{Key: "ADDR", Value: []byte("192.168.0.1"), Format: ""},
+				{Key: "AGE", Value: []byte("20"), Format: ""},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &env{
+				prefixs: tt.fields.prefixs,
+			}
+			got := e.load(tt.args.envStrings)
+			if !reflect.DeepEqual(tt.want, got) {
+				t.Errorf("env.load() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
Repository: go-kratos/kratos
Pull request #2041 (2022-05-26 02:45:25)

feat:add context for log
feat:add context for log


Patch:
diff --git a/log/global.go b/log/global.go
index 72f871f7..a44d0b76 100644
--- a/log/global.go
+++ b/log/global.go
@@ -1,6 +1,7 @@
 package log
 
 import (
+	"context"
 	"sync"
 )
 
@@ -46,6 +47,10 @@ func Log(level Level, keyvals ...interface{}) {
 	global.helper.Log(level, keyvals...)
 }
 
+func Context(ctx context.Context) *Helper {
+	return global.helper.WithContext(ctx)
+}
+
 // Debug logs a message at debug level.
 func Debug(a ...interface{}) {
 	global.helper.Debug(a...)


Test patch:
diff --git a/log/global_test.go b/log/global_test.go
index 5d2f2c8f..91482331 100644
--- a/log/global_test.go
+++ b/log/global_test.go
@@ -2,6 +2,7 @@ package log
 
 import (
 	"bytes"
+	"context"
 	"fmt"
 	"os"
 	"strings"
@@ -83,3 +84,12 @@ func TestGlobalLogUpdate(t *testing.T) {
 		t.Errorf("Expected: %s, got: %s", expected, buffer.String())
 	}
 }
+
+func TestGolbalContext(t *testing.T) {
+	buffer := &bytes.Buffer{}
+	SetLogger(NewStdLogger(buffer))
+	Context(context.Background()).Infof("111")
+	if buffer.String() != "INFO msg=111\n" {
+		t.Errorf("Expected:%s, got:%s", "INFO msg=111", buffer.String())
+	}
+}
Repository: go-kratos/kratos
Pull request #2074 (2022-06-02 10:32:46)

transport/http(feat): add redirector to forward request
```go
return http.NewRedirect(url, code)
```


Patch:
diff --git a/transport/http/codec.go b/transport/http/codec.go
index 79db5747..176e599a 100644
--- a/transport/http/codec.go
+++ b/transport/http/codec.go
@@ -12,6 +12,12 @@ import (
 // SupportPackageIsVersion1 These constants should not be referenced from any other code.
 const SupportPackageIsVersion1 = true
 
+// Redirector replies to the request with a redirect to url
+// which may be a path relative to the request path.
+type Redirector interface {
+	Redirect() (string, int)
+}
+
 // Request type net/http.
 type Request = http.Request
 
@@ -49,8 +55,12 @@ func DefaultRequestDecoder(r *http.Request, v interface{}) error {
 // DefaultResponseEncoder encodes the object to the HTTP response.
 func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
 	if v == nil {
-		_, err := w.Write(nil)
-		return err
+		return nil
+	}
+	if rd, ok := v.(Redirector); ok {
+		url, code := rd.Redirect()
+		http.Redirect(w, r, url, code)
+		return nil
 	}
 	codec, _ := CodecForRequest(r, "Accept")
 	data, err := codec.Marshal(v)
diff --git a/transport/http/redirect.go b/transport/http/redirect.go
new file mode 100644
index 00000000..cb98ac09
--- /dev/null
+++ b/transport/http/redirect.go
@@ -0,0 +1,18 @@
+package http
+
+type redirect struct {
+	URL  string
+	Code int
+}
+
+func (r *redirect) Redirect() (string, int) {
+	return r.URL, r.Code
+}
+
+// NewRedirect new a redirect with url, which may be a path relative to the request path.
+// The provided code should be in the 3xx range and is usually StatusMovedPermanently, StatusFound or StatusSeeOther.
+// If the Content-Type header has not been set, Redirect sets it to "text/html; charset=utf-8" and writes a small HTML body.
+// Setting the Content-Type header to any value, including nil, disables that behavior.
+func NewRedirect(url string, code int) Redirector {
+	return &redirect{URL: url, Code: code}
+}


Test patch:
diff --git a/transport/http/redirect_test.go b/transport/http/redirect_test.go
new file mode 100644
index 00000000..b98bf4f0
--- /dev/null
+++ b/transport/http/redirect_test.go
@@ -0,0 +1,23 @@
+package http
+
+import (
+	"net/http/httptest"
+	"testing"
+)
+
+func TestRedirect(t *testing.T) {
+	var (
+		redirectURL  = "/redirect"
+		redirectCode = 302
+	)
+	r := httptest.NewRequest("POST", "/test", nil)
+	w := httptest.NewRecorder()
+	_ = DefaultResponseEncoder(w, r, NewRedirect(redirectURL, redirectCode))
+
+	if w.Code != redirectCode {
+		t.Fatalf("want %d but got %d", redirectCode, w.Code)
+	}
+	if v := w.Header().Get("Location"); v != redirectURL {
+		t.Fatalf("want %s but got %s", redirectURL, v)
+	}
+}
Repository: go-kratos/kratos
Pull request #1481 (2021-09-15 08:55:04)

fix(internal/host): fix bug of host.Extract
<!--
🎉 Thanks for sending a pull request to Kratos! Here are some tips for you:

1. If this is your first time contributing to Kratos, please read our contribution guide: https://go-kratos.dev/en/docs/community/contribution/
2. Ensure you have added or ran the appropriate tests and lint for your PR, please use `make lint` and `make test` before filing your PR, use `make clean` to tidy your go mod.
3. If the PR is unfinished, you may need mark it as a WIP(Work In Progress) PR or draft PR
4. Please use a conventional commits format title: `<type>[optional scope]: <description>`
    
    Some suggestion on <type>:

    fix: A bug fix
    feat: A new feature
    test: Adding missing tests or correcting existing tests
    refactor: A code change that neither fixes a bug nor adds a feature
    break: Changes has break change

    docs: Documentation only changes
    deps: Changes external dependencies
    style: Changes that do not affect the meaning of the code (white-space, formatting, etc)
    chore Daily work, examples, etc.
    ci: Changes to our CI configuration files and scripts
-->

#### Description (what this PR does / why we need it):
<!--
* The description should include the motivation for this PR or contrast this with previous behavior
-->


#### Which issue(s) this PR fixes (resolves / be part of):
<!--
* Automatically closes linked issue when PR is merged.
* If you PR is not fully resolved issue, please use `part of #<issue number>` instead.

Usage: `fixes/resolves #<issue number>`, or `fixes/resolves (paste link of issue)`.
-->
fixes #

#### Other special notes for reviewer:
<!--
* Somethings that need extra attention for reviewer
* Some additional notes, TODO list, etc.
-->



Patch:
diff --git a/internal/host/host.go b/internal/host/host.go
index 3f1418aa..ac0cf212 100644
--- a/internal/host/host.go
+++ b/internal/host/host.go
@@ -36,7 +36,7 @@ func Port(lis net.Listener) (int, bool) {
 // Extract returns a private addr and port.
 func Extract(hostPort string, lis net.Listener) (string, error) {
 	addr, port, err := net.SplitHostPort(hostPort)
-	if err != nil {
+	if err != nil && lis == nil {
 		return "", err
 	}
 	if lis != nil {


Test patch:
diff --git a/internal/host/host_test.go b/internal/host/host_test.go
index f8f63629..102be651 100644
--- a/internal/host/host_test.go
+++ b/internal/host/host_test.go
@@ -76,6 +76,13 @@ func TestExtract(t *testing.T) {
 			}
 		})
 	}
+	lis, err := net.Listen("tcp", ":12345")
+	assert.NoError(t, err)
+	res, err := Extract("", lis)
+	assert.NoError(t, err)
+	expect, err := Extract(lis.Addr().String(), nil)
+	assert.NoError(t, err)
+	assert.Equal(t, expect, res)
 }
 
 func TestExtract2(t *testing.T) {