func (protocol *HumanReadableJsonProtocol) parseStruct(fieldsList Array, request interface{}) error { if object, ok := toJsonCheck(request); ok { // fmt.Println("ReadStructBegin", object) for key, value := range object { // fmt.Println("ReadFieldBegin") // Get the information of the field (type, name, etc) fieldInfo := fieldsList.findInJsonArray(nameKey, key) if fieldInfo == nil { // Field doesn't exist return errors.New("Unexpected key " + key) } // Get the Thrift Type of the field fieldType, err := protocol.StringToTypeId(fieldInfo.getStringVal(typeIdKey)) if err != nil { return err } // Add the name, type and key (1:, 2:, 3:, etc) to params protocol.add(key, fieldType, fieldInfo.getDefaultInt16Val(keyKey, 0)) // fmt.Println(key, fieldType, fieldInfo.GetInt16Val(keyKey)) // Recursively parse the field err = protocol.parse(fieldInfo, value, typeIdKey, typeKey) if err != nil { return err } // fmt.Println("ReadFieldEnd") } // Finish parsing struct protocol.add("", thrift.TType(thrift.STOP), int16(-1)) // fmt.Println("ReadStructEnd") return nil } else { return errors.New(fmt.Sprintf("Expected Json Object got %t", request)) } }
func (protocol *HumanReadableJsonProtocol) StringToTypeId(fieldType string) (thrift.TType, error) { switch fieldType { case "bool": return thrift.TType(thrift.BOOL), nil case "i8": return thrift.TType(thrift.BYTE), nil case "i16": return thrift.TType(thrift.I16), nil case "i32": return thrift.TType(thrift.I32), nil case "i64": return thrift.TType(thrift.I64), nil case "double": return thrift.TType(thrift.DOUBLE), nil case "string": return thrift.TType(thrift.STRING), nil case "struct", "union", "exception": return thrift.TType(thrift.STRUCT), nil case "map": return thrift.TType(thrift.MAP), nil case "set": return thrift.TType(thrift.SET), nil case "list": return thrift.TType(thrift.LIST), nil } e := fmt.Errorf("Unknown type identifier: %s", fieldType) return thrift.TType(thrift.STOP), thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, e) }
func (protocol *HumanReadableJsonProtocol) ReadMessageBegin() (string, thrift.TMessageType, int32, error) { // Read all data and parse out the JSON object var data []byte data, err := ioutil.ReadAll(protocol.trans) if err != nil && err != io.EOF && err.Error() != "EOF" { // Uggh thrift wraps it inside its own error return "", thrift.INVALID_TMESSAGE_TYPE, 0, thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, err) } protocol.request, err = NewJson(data) if err != nil { return "", thrift.INVALID_TMESSAGE_TYPE, 0, thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, err) } // Get the method info corresponding to method being called name := protocol.request.getDefaultStringVal(methodKey, "") methodInfo, methodInfoErr := protocol.getMethodInfo(protocol.service, name) // Type Id tells whether it is a request (CALL) or response (REPLY) or error (EXCEPTION) // Seq Id == 0 for CALL and 1 for REPLY, EXCEPTION always typeId, seqId := protocol.getMessageTypeAndSeq(methodInfo) if protocol.request.hasKey(argumentsKey) { /** CALL */ if methodInfoErr != nil { // Method not found, STOP processing and send back up, // Generated code will send an error saying "Unknown function" protocol.add("", thrift.TType(thrift.STOP), int16(-1)) return name, typeId, seqId, nil } // Parse out the arguments struct // Send it the arguments struct in both the method metadata and the request protocol.err = protocol.parseStruct(methodInfo.getArrayVal(argumentsKey), protocol.request.getJsonVal(argumentsKey)) } else if protocol.request.hasKey(resultKey) { /** REPLY */ if methodInfoErr != nil { // Method not found, STOP processing and send back up, // Generated code will send an error saying "Unknown function" protocol.add("", thrift.TType(thrift.STOP), int16(-1)) return name, typeId, seqId, nil } result := protocol.request.getJsonVal(resultKey) // The result will either have "success" or the name of the error that was thrown if result.hasKey(successKey) { // Figure out the return type returnType, err := protocol.StringToTypeId(methodInfo.getStringVal(returnTypeIdKey)) if err != nil { protocol.err = err } else { // Add a field with the returnType protocol.add("", returnType, int16(0)) // Parse the result protocol.err = protocol.parse(methodInfo, result[successKey], returnTypeIdKey, returnTypeKey) // Finish parsing protocol.add("", thrift.TType(thrift.STOP), int16(-1)) } } else if len(result) == 0 { // There was nothing in result. The return type is void protocol.add("", thrift.TType(thrift.STOP), int16(-1)) } else { // There was an error, get the error variable name var errName string for key, _ := range result { errName = key break } errInfo := methodInfo.getArrayVal(exceptionsKey).findInJsonArray(nameKey, errName) if errInfo == nil { // Error doesn't exist in the Thrift definition return "", thrift.INVALID_TMESSAGE_TYPE, 0, thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, errors.New("Unable to parse result")) } // Begin Parsing Error (which is just a struct) protocol.add(errName, thrift.TType(thrift.STRUCT), errInfo.getDefaultInt16Val(keyKey, 1)) // Parse Error protocol.err = protocol.parse(errInfo, result.getJsonVal(errName), typeIdKey, typeKey) // Finish Parsing error protocol.add("", thrift.TType(thrift.STOP), int16(-1)) } } else if protocol.request.hasKey(exceptionKey) { // Error other than one defined in the method signature. It will have a string and an int32 // Add String field protocol.add("", thrift.TType(thrift.STRING), int16(1)) // Parse string protocol.add(protocol.request.getJsonVal(exceptionKey).getDefaultStringVal(messageKey, "")) // Add int32 protocol.add("", thrift.TType(thrift.I32), int16(2)) // Parse int32 protocol.add(protocol.request.getJsonVal(exceptionKey).getDefaultInt32Val(typeKey, thrift.UNKNOWN_APPLICATION_EXCEPTION)) // Finish Parsing protocol.add("", thrift.TType(thrift.STOP), int16(-1)) } else { // Don't recognize what kind of message this is return "", thrift.INVALID_TMESSAGE_TYPE, 0, thrift.NewTProtocolExceptionWithType(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, errors.New("Invalid type")) } // fmt.Println(protocol.params) return name, typeId, seqId, nil }