in protocol/dubbo/hessian2/hessian_response.go [69:172]
func packResponse(header DubboHeader, ret interface{}) ([]byte, error) {
var byteArray []byte
response := EnsureResponse(ret)
hb := header.Type == PackageHeartbeat
// magic
if hb {
byteArray = append(byteArray, DubboResponseHeartbeatHeader[:]...)
} else {
byteArray = append(byteArray, DubboResponseHeaderBytes[:]...)
}
// set serialID, identify serialization types, eg: fastjson->6, hessian2->2
byteArray[2] |= header.SerialID & SERIAL_MASK
// response status
if header.ResponseStatus != 0 {
byteArray[3] = header.ResponseStatus
}
// request id
binary.BigEndian.PutUint64(byteArray[4:], uint64(header.ID))
// body
encoder := hessian.NewEncoder()
encoder.Append(byteArray[:HEADER_LENGTH])
if header.ResponseStatus == Response_OK {
if hb {
if err := encoder.Encode(nil); err != nil {
logger.Warnf("Encode(nil) = %v", err)
}
} else {
atta := isSupportResponseAttachment(response.Attachments[DUBBO_VERSION_KEY])
var resWithException, resValue, resNullValue int32
if atta {
resWithException = RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS
resValue = RESPONSE_VALUE_WITH_ATTACHMENTS
resNullValue = RESPONSE_NULL_VALUE_WITH_ATTACHMENTS
} else {
resWithException = RESPONSE_WITH_EXCEPTION
resValue = RESPONSE_VALUE
resNullValue = RESPONSE_NULL_VALUE
}
if response.Exception != nil { // throw error
err := encoder.Encode(resWithException)
if err != nil {
return nil, perrors.Errorf("encoding response failed: %v", err)
}
if t, ok := response.Exception.(java_exception.Throwabler); ok {
err = encoder.Encode(t)
} else {
err = encoder.Encode(java_exception.NewThrowable(response.Exception.Error()))
}
if err != nil {
return nil, perrors.Errorf("encoding exception failed: %v", err)
}
} else {
if response.RspObj == nil {
if err := encoder.Encode(resNullValue); err != nil {
return nil, perrors.Errorf("encoding null value failed: %v", err)
}
} else {
if err := encoder.Encode(resValue); err != nil {
return nil, perrors.Errorf("encoding response value failed: %v", err)
}
if err := encoder.Encode(response.RspObj); err != nil {
return nil, perrors.Errorf("encoding response failed: %v", err)
}
}
}
// attachments
if atta {
if err := encoder.Encode(response.Attachments); err != nil {
return nil, perrors.Errorf("encoding response attachements failed: %v", err)
}
}
}
} else {
var err error
if response.Exception != nil { // throw error
err = encoder.Encode(response.Exception.Error())
} else {
err = encoder.Encode(response.RspObj)
}
if err != nil {
return nil, perrors.Errorf("encoding error failed: %v", err)
}
}
byteArray = encoder.Buffer()
byteArray = hessian.EncNull(byteArray) // if not, "java client" will throw exception "unexpected end of file"
pkgLen := len(byteArray)
if pkgLen > int(DEFAULT_LEN) { // recommand 8M
logger.Warnf("Data length %d too large, recommand max payload %d. "+
"Dubbo java can't handle the package whose size greater than %d!!!", pkgLen, DEFAULT_LEN, DEFAULT_LEN)
}
// byteArray{body length}
binary.BigEndian.PutUint32(byteArray[12:], uint32(pkgLen-HEADER_LENGTH))
return byteArray, nil
}