grpc server protobuf conversion parameter query request to the http

premise

After receiving the request grpc service request, it is necessary to convert the argument to http, requests to other interfaces.

Use grpc go as a server, a data protocol is protobuf

Think of several solutions:

  • 1. compiled pb.go file, there are a string (), all parameters can be printed out, are separated by spaces between parameters and parameter values ​​k: v form, but without the quotation marks, not json format

  • 2. The received data is converted into json, directly json format transmission request
  • The request is passed over the reflector to a fixed struct, to obtain specific properties and methods to obtain this property, then added to url.values ​​{}, re-encode () sends a request

achieve

plan 1

1 is a relatively simple scheme, a space is divided, and the parameter values ​​obtained, then according to ":" obtained by dividing the parameter, the value added to url.values ​​{}

code show as below:

param := url.Values{}
//得到请求的字符串形式
rs := strings.Split(request.String(), " ")
    for _, v := range rs {
        if v != "" {
            vv := strings.Split(v, ":")
            param.Add(vv[0], strings.Trim(vv[1], "\""))
            vv := strings.SplitN(v, ":", 2)
            //转换成
            val, e := strconv.Unquote(vv[1])
            log.Print(val, e)
            if e == nil {
                param.Add(vv[0], val)
            }
        }
    }

Early running OK, the latter encountered two problems:

  • 1. The value submitted in time spaces, there will be problems segmentation
  • 2. Chinese characters get is utf8

Abandon Scenario 1

Scenario 2

The data is first converted into JSON, and then parsed into map form [string] string, the purpose is to convert to string values ​​are omitted

str, _ := json.Marshal(request)
    jsonstr := string(str)

    m := make(map[string]interface{})
    e := json.Unmarshal([]byte(jsonstr), &m)
    param := url.Values{}
    if e != nil {
        return param
    }

    for k, v := range m {
        sv := fmt.Sprint(v)
        param.Add(k, sv)
    }

Results: For the Chinese there is a space problem is solved, but the digital conversion will int64 type into a float, the conversion in question

Scenario 3

Reflecting actual struct go according to reflect the package, go pb compile the file name and property in the struct proto file is not the same, need to be based on the actual parameter name tag attributes

code show as below:

    ty := reflect.TypeOf(request).Elem()
    #得到struct的属性数量
    fieldnum := ty.NumField()
    
    #实际数据的指针
    ob := reflect.ValueOf(request)
    param := url.Values{}
    #由于编译好的属性最后3位不用
    for i := 0; i < fieldnum-3; i++ {
        f := ty.Field(i).Tag.Get("json")
        fv := strings.Split(f, ",")
        k := fv[0]

        fieldname := ty.Field(i).Name
        ret := ob.MethodByName("Get" + fieldname).Call(nil)
        if !ret[0].IsZero() {
            # 这一步,用了很巧的办法把各个类型转换成了string才能加入到param里
            v := fmt.Sprint(ret[0])
            param.Add(k, v)
        }
    }
    return param

Guess you like

Origin www.cnblogs.com/efan/p/12061823.html