mirror of
https://github.com/go-kratos/kratos.git
synced 2025-03-11 14:49:42 +02:00
parent
dc80d0865f
commit
0ff1c6f89a
1
go.mod
1
go.mod
@ -8,6 +8,7 @@ require (
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/stretchr/testify v1.7.0
|
||||
go.opentelemetry.io/otel v0.20.0
|
||||
go.opentelemetry.io/otel/trace v0.20.0
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||
|
1
go.sum
1
go.sum
@ -43,6 +43,7 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
|
@ -307,7 +307,7 @@ func DefaultErrorDecoder(ctx context.Context, res *http.Response) error {
|
||||
|
||||
// CodecForResponse get encoding.Codec via http.Response
|
||||
func CodecForResponse(r *http.Response) encoding.Codec {
|
||||
codec := encoding.GetCodec(httputil.ContentSubtype("Content-Type"))
|
||||
codec := encoding.GetCodec(httputil.ContentSubtype(r.Header.Get("Content-Type")))
|
||||
if codec != nil {
|
||||
return codec
|
||||
}
|
||||
|
174
transport/http/client_test.go
Normal file
174
transport/http/client_test.go
Normal file
@ -0,0 +1,174 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"io/ioutil"
|
||||
nethttp "net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/registry"
|
||||
)
|
||||
|
||||
type mockRoundTripper struct {
|
||||
}
|
||||
|
||||
func (rt *mockRoundTripper) RoundTrip(req *nethttp.Request) (resp *nethttp.Response, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func TestWithTransport(t *testing.T) {
|
||||
ov := &mockRoundTripper{}
|
||||
o := WithTransport(ov)
|
||||
co := &clientOptions{}
|
||||
o(co)
|
||||
assert.Equal(t, co.transport, ov)
|
||||
}
|
||||
|
||||
func TestWithTimeout(t *testing.T) {
|
||||
ov := 1 * time.Second
|
||||
o := WithTimeout(ov)
|
||||
co := &clientOptions{}
|
||||
o(co)
|
||||
assert.Equal(t, co.timeout, ov)
|
||||
}
|
||||
|
||||
func TestWithBalancer(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestWithUserAgent(t *testing.T) {
|
||||
ov := "kratos"
|
||||
o := WithUserAgent(ov)
|
||||
co := &clientOptions{}
|
||||
o(co)
|
||||
assert.Equal(t, co.userAgent, ov)
|
||||
}
|
||||
|
||||
func TestWithMiddleware(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithEndpoint(t *testing.T) {
|
||||
ov := "some-endpoint"
|
||||
o := WithEndpoint(ov)
|
||||
co := &clientOptions{}
|
||||
o(co)
|
||||
assert.Equal(t, co.endpoint, ov)
|
||||
}
|
||||
|
||||
func TestWithRequestEncoder(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestWithResponseDecoder(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestWithErrorDecoder(t *testing.T) {
|
||||
}
|
||||
|
||||
type mockDiscovery struct {
|
||||
}
|
||||
|
||||
func (*mockDiscovery) GetService(ctx context.Context, serviceName string) ([]*registry.ServiceInstance, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (*mockDiscovery) Watch(ctx context.Context, serviceName string) (registry.Watcher, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestWithDiscovery(t *testing.T) {
|
||||
ov := &mockDiscovery{}
|
||||
o := WithDiscovery(ov)
|
||||
co := &clientOptions{}
|
||||
o(co)
|
||||
assert.Equal(t, co.discovery, ov)
|
||||
}
|
||||
|
||||
func TestDefaultRequestEncoder(t *testing.T) {
|
||||
req1 := &nethttp.Request{
|
||||
Header: make(nethttp.Header),
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
|
||||
}
|
||||
req1.Header.Set("Content-Type", "application/xml")
|
||||
|
||||
v1 := &struct {
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
}{"a", 1}
|
||||
b, err1 := DefaultRequestEncoder(context.TODO(), "application/json", v1)
|
||||
assert.Nil(t, err1)
|
||||
v1b := &struct {
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
}{}
|
||||
err1 = json.Unmarshal(b, v1b)
|
||||
assert.Nil(t, err1)
|
||||
assert.Equal(t, v1, v1b)
|
||||
}
|
||||
|
||||
func TestDefaultResponseDecoder(t *testing.T) {
|
||||
resp1 := &nethttp.Response{
|
||||
Header: make(nethttp.Header),
|
||||
StatusCode: 200,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
|
||||
}
|
||||
v1 := &struct {
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
}{}
|
||||
err1 := DefaultResponseDecoder(context.TODO(), resp1, &v1)
|
||||
assert.Nil(t, err1)
|
||||
assert.Equal(t, "1", v1.A)
|
||||
assert.Equal(t, int64(2), v1.B)
|
||||
|
||||
resp2 := &nethttp.Response{
|
||||
Header: make(nethttp.Header),
|
||||
StatusCode: 200,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("{badjson}")),
|
||||
}
|
||||
v2 := &struct {
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
}{}
|
||||
err2 := DefaultResponseDecoder(context.TODO(), resp2, &v2)
|
||||
terr1 := &json.SyntaxError{}
|
||||
assert.ErrorAs(t, err2, &terr1)
|
||||
}
|
||||
|
||||
func TestDefaultErrorDecoder(t *testing.T) {
|
||||
for i := 200; i < 300; i++ {
|
||||
resp := &nethttp.Response{Header: make(nethttp.Header), StatusCode: i}
|
||||
assert.Nil(t, DefaultErrorDecoder(context.TODO(), resp))
|
||||
}
|
||||
resp1 := &nethttp.Response{
|
||||
Header: make(nethttp.Header),
|
||||
StatusCode: 300,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("{\"foo\":\"bar\"}")),
|
||||
}
|
||||
assert.Error(t, DefaultErrorDecoder(context.TODO(), resp1))
|
||||
|
||||
resp2 := &nethttp.Response{
|
||||
Header: make(nethttp.Header),
|
||||
StatusCode: 500,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("{\"code\":54321, \"message\": \"hi\", \"reason\": \"FOO\"}")),
|
||||
}
|
||||
err2 := DefaultErrorDecoder(context.TODO(), resp2)
|
||||
assert.Error(t, err2)
|
||||
assert.Equal(t, int32(54321), err2.(*errors.Error).GetCode())
|
||||
assert.Equal(t, "hi", err2.(*errors.Error).GetMessage())
|
||||
assert.Equal(t, "FOO", err2.(*errors.Error).GetReason())
|
||||
}
|
||||
|
||||
func TestCodecForResponse(t *testing.T) {
|
||||
resp := &nethttp.Response{Header: make(nethttp.Header)}
|
||||
resp.Header.Set("Content-Type", "application/xml")
|
||||
c := CodecForResponse(resp)
|
||||
assert.Equal(t, "xml", c.Name())
|
||||
}
|
108
transport/http/codec_test.go
Normal file
108
transport/http/codec_test.go
Normal file
@ -0,0 +1,108 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
nethttp "net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDefaultRequestDecoder(t *testing.T) {
|
||||
req1 := &nethttp.Request{
|
||||
Header: make(nethttp.Header),
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
|
||||
}
|
||||
req1.Header.Set("Content-Type", "application/json")
|
||||
|
||||
v1 := &struct {
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
}{}
|
||||
err1 := DefaultRequestDecoder(req1, &v1)
|
||||
assert.Nil(t, err1)
|
||||
assert.Equal(t, "1", v1.A)
|
||||
assert.Equal(t, int64(2), v1.B)
|
||||
}
|
||||
|
||||
type mockResponseWriter struct {
|
||||
StatusCode int
|
||||
Data []byte
|
||||
header nethttp.Header
|
||||
}
|
||||
|
||||
func (w *mockResponseWriter) Header() nethttp.Header {
|
||||
return w.header
|
||||
}
|
||||
|
||||
func (w *mockResponseWriter) Write(b []byte) (int, error) {
|
||||
w.Data = b
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (w *mockResponseWriter) WriteHeader(statusCode int) {
|
||||
w.StatusCode = statusCode
|
||||
}
|
||||
|
||||
type dataWithStatusCode struct {
|
||||
statusCode int
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
}
|
||||
|
||||
func (d *dataWithStatusCode) StatusCode() int {
|
||||
return d.statusCode
|
||||
}
|
||||
|
||||
func TestDefaultResponseEncoder(t *testing.T) {
|
||||
w := &mockResponseWriter{header: make(nethttp.Header)}
|
||||
req1 := &nethttp.Request{
|
||||
Header: make(nethttp.Header),
|
||||
}
|
||||
req1.Header.Set("Content-Type", "application/json")
|
||||
|
||||
v1 := &dataWithStatusCode{statusCode: 201, A: "1", B: 2}
|
||||
err := DefaultResponseEncoder(w, req1, v1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
|
||||
assert.Equal(t, 201, w.StatusCode)
|
||||
assert.NotNil(t, w.Data)
|
||||
}
|
||||
|
||||
func TestDefaultResponseEncoderWithError(t *testing.T) {
|
||||
w := &mockResponseWriter{header: make(nethttp.Header)}
|
||||
req1 := &nethttp.Request{
|
||||
Header: make(nethttp.Header),
|
||||
}
|
||||
req1.Header.Set("Content-Type", "application/json")
|
||||
|
||||
v1 := &errors.Error{Code: 511}
|
||||
err := DefaultResponseEncoder(w, req1, v1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
|
||||
assert.Equal(t, 511, w.StatusCode)
|
||||
assert.NotNil(t, w.Data)
|
||||
}
|
||||
|
||||
func TestCodecForRequest(t *testing.T) {
|
||||
req1 := &nethttp.Request{
|
||||
Header: make(nethttp.Header),
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("<xml></xml>")),
|
||||
}
|
||||
req1.Header.Set("Content-Type", "application/xml")
|
||||
|
||||
c, ok := CodecForRequest(req1, "Content-Type")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "xml", c.Name())
|
||||
|
||||
req2 := &nethttp.Request{
|
||||
Header: make(nethttp.Header),
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
|
||||
}
|
||||
req2.Header.Set("Content-Type", "blablablabla")
|
||||
|
||||
c, ok = CodecForRequest(req2, "Content-Type")
|
||||
assert.False(t, ok)
|
||||
assert.Equal(t, "json", c.Name())
|
||||
}
|
@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/internal/host"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type testKey struct{}
|
||||
@ -103,3 +104,35 @@ func testClient(t *testing.T, srv *Server) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkServer(b *testing.B) {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
data := &testData{Path: r.RequestURI}
|
||||
json.NewEncoder(w).Encode(data)
|
||||
if r.Context().Value(testKey{}) != "test" {
|
||||
w.WriteHeader(500)
|
||||
}
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, testKey{}, "test")
|
||||
srv := NewServer()
|
||||
srv.HandleFunc("/index", fn)
|
||||
go func() {
|
||||
if err := srv.Start(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
time.Sleep(time.Second)
|
||||
port, ok := host.Port(srv.lis)
|
||||
assert.True(b, ok)
|
||||
client, err := NewClient(context.Background(), WithEndpoint(fmt.Sprintf("127.0.0.1:%d", port)))
|
||||
assert.NoError(b, err)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var res testData
|
||||
err := client.Invoke(context.Background(), "POST", "/index", nil, &res)
|
||||
assert.NoError(b, err)
|
||||
}
|
||||
srv.Stop(ctx)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user