github.com/cloudwego/kitex@v0.9.0/pkg/generic/httpthrift_codec_test.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package generic 18 19 import ( 20 "bytes" 21 "context" 22 "io/ioutil" 23 "net/http" 24 "testing" 25 26 "github.com/bytedance/sonic" 27 "github.com/cloudwego/dynamicgo/conv" 28 29 "github.com/cloudwego/kitex/internal/mocks" 30 "github.com/cloudwego/kitex/internal/test" 31 "github.com/cloudwego/kitex/pkg/generic/descriptor" 32 "github.com/cloudwego/kitex/pkg/remote" 33 "github.com/cloudwego/kitex/pkg/rpcinfo" 34 "github.com/cloudwego/kitex/transport" 35 ) 36 37 var customJson = sonic.Config{ 38 EscapeHTML: true, 39 UseNumber: true, 40 }.Froze() 41 42 func TestFromHTTPRequest(t *testing.T) { 43 jsonBody := `{"a": 1111111111111, "b": "hello"}` 44 req, err := http.NewRequest(http.MethodPost, "http://example.com", bytes.NewBufferString(jsonBody)) 45 test.Assert(t, err == nil) 46 customReq, err := FromHTTPRequest(req) 47 test.Assert(t, err == nil) 48 test.DeepEqual(t, string(customReq.RawBody), jsonBody) 49 } 50 51 func TestHttpThriftCodec(t *testing.T) { 52 // without dynamicgo 53 p, err := NewThriftFileProvider("./http_test/idl/binary_echo.thrift") 54 test.Assert(t, err == nil) 55 gOpts := &Options{dynamicgoConvOpts: DefaultHTTPDynamicGoConvOpts} 56 htc, err := newHTTPThriftCodec(p, thriftCodec, gOpts) 57 test.Assert(t, err == nil) 58 test.Assert(t, !htc.dynamicgoEnabled) 59 test.Assert(t, !htc.useRawBodyForHTTPResp) 60 test.DeepEqual(t, htc.convOpts, conv.Options{}) 61 test.DeepEqual(t, htc.convOptsWithThriftBase, conv.Options{}) 62 defer htc.Close() 63 test.Assert(t, htc.Name() == "HttpThrift") 64 65 req := &HTTPRequest{Request: getStdHttpRequest()} 66 // wrong 67 method, err := htc.getMethod("test") 68 test.Assert(t, err.Error() == "req is invalid, need descriptor.HTTPRequest" && method == nil) 69 // right 70 method, err = htc.getMethod(req) 71 test.Assert(t, err == nil && method.Name == "BinaryEcho") 72 73 ctx := context.Background() 74 sendMsg := initHttpSendMsg() 75 76 // Marshal side 77 out := remote.NewWriterBuffer(256) 78 err = htc.Marshal(ctx, sendMsg, out) 79 test.Assert(t, err == nil) 80 81 // Unmarshal side 82 recvMsg := initHttpRecvMsg() 83 buf, err := out.Bytes() 84 test.Assert(t, err == nil) 85 recvMsg.SetPayloadLen(len(buf)) 86 in := remote.NewReaderBuffer(buf) 87 err = htc.Unmarshal(ctx, recvMsg, in) 88 test.Assert(t, err == nil) 89 } 90 91 func TestHttpThriftCodecWithDynamicGo(t *testing.T) { 92 // with dynamicgo 93 p, err := NewThriftFileProviderWithDynamicGo("./http_test/idl/binary_echo.thrift") 94 test.Assert(t, err == nil) 95 gOpts := &Options{dynamicgoConvOpts: DefaultHTTPDynamicGoConvOpts, useRawBodyForHTTPResp: true} 96 htc, err := newHTTPThriftCodec(p, thriftCodec, gOpts) 97 test.Assert(t, err == nil) 98 test.Assert(t, htc.dynamicgoEnabled) 99 test.Assert(t, htc.useRawBodyForHTTPResp) 100 test.DeepEqual(t, htc.convOpts, DefaultHTTPDynamicGoConvOpts) 101 convOptsWithThriftBase := DefaultHTTPDynamicGoConvOpts 102 convOptsWithThriftBase.EnableThriftBase = true 103 test.DeepEqual(t, htc.convOptsWithThriftBase, convOptsWithThriftBase) 104 defer htc.Close() 105 test.Assert(t, htc.Name() == "HttpThrift") 106 107 req := &HTTPRequest{Request: getStdHttpRequest()} 108 // wrong 109 method, err := htc.getMethod("test") 110 test.Assert(t, err.Error() == "req is invalid, need descriptor.HTTPRequest" && method == nil) 111 // right 112 method, err = htc.getMethod(req) 113 test.Assert(t, err == nil && method.Name == "BinaryEcho") 114 115 ctx := context.Background() 116 sendMsg := initHttpSendMsg() 117 118 // Marshal side 119 out := remote.NewWriterBuffer(256) 120 err = htc.Marshal(ctx, sendMsg, out) 121 test.Assert(t, err == nil) 122 123 // Unmarshal side 124 recvMsg := initHttpRecvMsg() 125 buf, err := out.Bytes() 126 test.Assert(t, err == nil) 127 recvMsg.SetPayloadLen(len(buf)) 128 in := remote.NewReaderBuffer(buf) 129 err = htc.Unmarshal(ctx, recvMsg, in) 130 test.Assert(t, err == nil) 131 } 132 133 func initHttpSendMsg() remote.Message { 134 stdReq := getStdHttpRequest() 135 b, err := stdReq.GetBody() 136 if err != nil { 137 panic(err) 138 } 139 rawBody, err := ioutil.ReadAll(b) 140 if err != nil { 141 panic(err) 142 } 143 req := &Args{ 144 Request: &descriptor.HTTPRequest{ 145 Request: stdReq, 146 RawBody: rawBody, 147 }, 148 Method: "BinaryEcho", 149 } 150 svcInfo := mocks.ServiceInfo() 151 ink := rpcinfo.NewInvocation("", "BinaryEcho") 152 ri := rpcinfo.NewRPCInfo(nil, nil, ink, nil, rpcinfo.NewRPCStats()) 153 msg := remote.NewMessage(req, svcInfo, ri, remote.Call, remote.Client) 154 msg.SetProtocolInfo(remote.NewProtocolInfo(transport.TTHeader, svcInfo.PayloadCodec)) 155 return msg 156 } 157 158 func initHttpRecvMsg() remote.Message { 159 req := &Args{ 160 Request: "Test", 161 Method: "BinaryEcho", 162 } 163 ink := rpcinfo.NewInvocation("", "BinaryEcho") 164 ri := rpcinfo.NewRPCInfo(nil, nil, ink, nil, rpcinfo.NewRPCStats()) 165 msg := remote.NewMessage(req, mocks.ServiceInfo(), ri, remote.Call, remote.Server) 166 return msg 167 } 168 169 func getStdHttpRequest() *http.Request { 170 body := map[string]interface{}{ 171 "msg": []byte("hello"), 172 "got_base64": true, 173 "num": "", 174 } 175 data, err := customJson.Marshal(body) 176 if err != nil { 177 panic(err) 178 } 179 stdReq, err := http.NewRequest(http.MethodGet, "/BinaryEcho", bytes.NewBuffer(data)) 180 if err != nil { 181 panic(err) 182 } 183 return stdReq 184 }