github.com/cloudwego/kitex@v0.9.0/pkg/generic/generic.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 package generic 19 20 import ( 21 "fmt" 22 23 "github.com/cloudwego/dynamicgo/conv" 24 25 "github.com/cloudwego/kitex/pkg/remote" 26 "github.com/cloudwego/kitex/pkg/remote/codec/protobuf" 27 "github.com/cloudwego/kitex/pkg/remote/codec/thrift" 28 "github.com/cloudwego/kitex/pkg/serviceinfo" 29 ) 30 31 // Generic ... 32 type Generic interface { 33 Closer 34 // PayloadCodec return codec implement 35 PayloadCodec() remote.PayloadCodec 36 // PayloadCodecType return the type of codec 37 PayloadCodecType() serviceinfo.PayloadCodec 38 // RawThriftBinaryGeneric must be framed 39 Framed() bool 40 // GetMethod to get method name if need 41 GetMethod(req interface{}, method string) (*Method, error) 42 } 43 44 // Method information 45 type Method struct { 46 Name string 47 Oneway bool 48 } 49 50 // BinaryThriftGeneric raw thrift binary Generic 51 func BinaryThriftGeneric() Generic { 52 return &binaryThriftGeneric{} 53 } 54 55 // MapThriftGeneric map mapping generic 56 // Base64 codec for binary field is disabled by default. You can change this option with SetBinaryWithBase64. 57 // eg: 58 // 59 // g, err := generic.MapThriftGeneric(p) 60 // SetBinaryWithBase64(g, true) 61 // 62 // String value is returned for binary field by default. You can change the return value to []byte for binary field with SetBinaryWithByteSlice. 63 // eg: 64 // 65 // SetBinaryWithByteSlice(g, true) 66 func MapThriftGeneric(p DescriptorProvider) (Generic, error) { 67 codec, err := newMapThriftCodec(p, thriftCodec) 68 if err != nil { 69 return nil, err 70 } 71 return &mapThriftGeneric{ 72 codec: codec, 73 }, nil 74 } 75 76 func MapThriftGenericForJSON(p DescriptorProvider) (Generic, error) { 77 codec, err := newMapThriftCodecForJSON(p, thriftCodec) 78 if err != nil { 79 return nil, err 80 } 81 return &mapThriftGeneric{ 82 codec: codec, 83 }, nil 84 } 85 86 // HTTPThriftGeneric http mapping Generic. 87 // Base64 codec for binary field is disabled by default. You can change this option with SetBinaryWithBase64. 88 // eg: 89 // 90 // g, err := generic.HTTPThriftGeneric(p) 91 // SetBinaryWithBase64(g, true) 92 func HTTPThriftGeneric(p DescriptorProvider, opts ...Option) (Generic, error) { 93 gOpts := &Options{dynamicgoConvOpts: DefaultHTTPDynamicGoConvOpts} 94 gOpts.apply(opts) 95 codec, err := newHTTPThriftCodec(p, thriftCodec, gOpts) 96 if err != nil { 97 return nil, err 98 } 99 return &httpThriftGeneric{codec: codec}, nil 100 } 101 102 func HTTPPbThriftGeneric(p DescriptorProvider, pbp PbDescriptorProvider) (Generic, error) { 103 codec, err := newHTTPPbThriftCodec(p, pbp, thriftCodec) 104 if err != nil { 105 return nil, err 106 } 107 return &httpPbThriftGeneric{ 108 codec: codec, 109 }, nil 110 } 111 112 // JSONThriftGeneric json mapping generic. 113 // Base64 codec for binary field is enabled by default. You can change this option with SetBinaryWithBase64. 114 // eg: 115 // 116 // g, err := generic.JSONThriftGeneric(p) 117 // SetBinaryWithBase64(g, false) 118 func JSONThriftGeneric(p DescriptorProvider, opts ...Option) (Generic, error) { 119 gOpts := &Options{dynamicgoConvOpts: DefaultJSONDynamicGoConvOpts} 120 gOpts.apply(opts) 121 codec, err := newJsonThriftCodec(p, thriftCodec, gOpts) 122 if err != nil { 123 return nil, err 124 } 125 return &jsonThriftGeneric{codec: codec}, nil 126 } 127 128 // JSONPbGeneric json mapping generic. 129 // Uses dynamicgo for json to protobufs conversion, so DynamicGo field is true by default. 130 func JSONPbGeneric(p PbDescriptorProviderDynamicGo, opts ...Option) (Generic, error) { 131 gOpts := &Options{dynamicgoConvOpts: conv.Options{}} 132 gOpts.apply(opts) 133 134 codec, err := newJsonPbCodec(p, pbCodec, gOpts) 135 if err != nil { 136 return nil, err 137 } 138 return &jsonPbGeneric{codec: codec}, nil 139 } 140 141 // SetBinaryWithBase64 enable/disable Base64 codec for binary field. 142 func SetBinaryWithBase64(g Generic, enable bool) error { 143 switch c := g.(type) { 144 case *httpThriftGeneric: 145 if c.codec == nil { 146 return fmt.Errorf("empty codec for %#v", c) 147 } 148 c.codec.binaryWithBase64 = enable 149 if c.codec.dynamicgoEnabled { 150 c.codec.convOpts.NoBase64Binary = !enable 151 c.codec.convOptsWithThriftBase.NoBase64Binary = !enable 152 } 153 case *jsonThriftGeneric: 154 if c.codec == nil { 155 return fmt.Errorf("empty codec for %#v", c) 156 } 157 c.codec.binaryWithBase64 = enable 158 if c.codec.dynamicgoEnabled { 159 c.codec.convOpts.NoBase64Binary = !enable 160 c.codec.convOptsWithThriftBase.NoBase64Binary = !enable 161 c.codec.convOptsWithException.NoBase64Binary = !enable 162 } 163 case *mapThriftGeneric: 164 if c.codec == nil { 165 return fmt.Errorf("empty codec for %#v", c) 166 } 167 c.codec.binaryWithBase64 = enable 168 default: 169 return fmt.Errorf("Base64Binary is unavailable for %#v", g) 170 } 171 return nil 172 } 173 174 // SetBinaryWithByteSlice enable/disable returning []byte for binary field. 175 func SetBinaryWithByteSlice(g Generic, enable bool) error { 176 switch c := g.(type) { 177 case *mapThriftGeneric: 178 if c.codec == nil { 179 return fmt.Errorf("empty codec for %#v", c) 180 } 181 c.codec.binaryWithByteSlice = enable 182 default: 183 return fmt.Errorf("returning []byte for binary fields is unavailable for %#v", g) 184 } 185 return nil 186 } 187 188 var thriftCodec = thrift.NewThriftCodec() 189 190 var pbCodec = protobuf.NewProtobufCodec() 191 192 type binaryThriftGeneric struct{} 193 194 func (g *binaryThriftGeneric) Framed() bool { 195 return true 196 } 197 198 func (g *binaryThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec { 199 return serviceinfo.Thrift 200 } 201 202 func (g *binaryThriftGeneric) PayloadCodec() remote.PayloadCodec { 203 pc := &binaryThriftCodec{thriftCodec} 204 return pc 205 } 206 207 func (g *binaryThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) { 208 return &Method{method, false}, nil 209 } 210 211 func (g *binaryThriftGeneric) Close() error { 212 return nil 213 } 214 215 type mapThriftGeneric struct { 216 codec *mapThriftCodec 217 } 218 219 func (g *mapThriftGeneric) Framed() bool { 220 return false 221 } 222 223 func (g *mapThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec { 224 return serviceinfo.Thrift 225 } 226 227 func (g *mapThriftGeneric) PayloadCodec() remote.PayloadCodec { 228 return g.codec 229 } 230 231 func (g *mapThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) { 232 return g.codec.getMethod(req, method) 233 } 234 235 func (g *mapThriftGeneric) Close() error { 236 return g.codec.Close() 237 } 238 239 type jsonThriftGeneric struct { 240 codec *jsonThriftCodec 241 } 242 243 func (g *jsonThriftGeneric) Framed() bool { 244 return g.codec.dynamicgoEnabled 245 } 246 247 func (g *jsonThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec { 248 return serviceinfo.Thrift 249 } 250 251 func (g *jsonThriftGeneric) PayloadCodec() remote.PayloadCodec { 252 return g.codec 253 } 254 255 func (g *jsonThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) { 256 return g.codec.getMethod(req, method) 257 } 258 259 func (g *jsonThriftGeneric) Close() error { 260 return g.codec.Close() 261 } 262 263 type jsonPbGeneric struct { 264 codec *jsonPbCodec 265 } 266 267 func (g *jsonPbGeneric) Framed() bool { 268 return false 269 } 270 271 func (g *jsonPbGeneric) PayloadCodecType() serviceinfo.PayloadCodec { 272 return serviceinfo.Protobuf 273 } 274 275 func (g *jsonPbGeneric) PayloadCodec() remote.PayloadCodec { 276 return g.codec 277 } 278 279 func (g *jsonPbGeneric) GetMethod(req interface{}, method string) (*Method, error) { 280 return g.codec.getMethod(req, method) 281 } 282 283 func (g *jsonPbGeneric) Close() error { 284 return g.codec.Close() 285 } 286 287 type httpThriftGeneric struct { 288 codec *httpThriftCodec 289 } 290 291 func (g *httpThriftGeneric) Framed() bool { 292 return g.codec.dynamicgoEnabled 293 } 294 295 func (g *httpThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec { 296 return serviceinfo.Thrift 297 } 298 299 func (g *httpThriftGeneric) PayloadCodec() remote.PayloadCodec { 300 return g.codec 301 } 302 303 func (g *httpThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) { 304 return g.codec.getMethod(req) 305 } 306 307 func (g *httpThriftGeneric) Close() error { 308 return g.codec.Close() 309 } 310 311 type httpPbThriftGeneric struct { 312 codec *httpPbThriftCodec 313 } 314 315 func (g *httpPbThriftGeneric) Framed() bool { 316 return false 317 } 318 319 func (g *httpPbThriftGeneric) PayloadCodecType() serviceinfo.PayloadCodec { 320 return serviceinfo.Thrift 321 } 322 323 func (g *httpPbThriftGeneric) PayloadCodec() remote.PayloadCodec { 324 return g.codec 325 } 326 327 func (g *httpPbThriftGeneric) GetMethod(req interface{}, method string) (*Method, error) { 328 return g.codec.getMethod(req) 329 } 330 331 func (g *httpPbThriftGeneric) Close() error { 332 return g.codec.Close() 333 }