func packResponse()

in protocol/dubbo/hessian2/hessian_response.go [69:172]


func packResponse(header DubboHeader, ret any) ([]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
}