FOLLY_NODISCARD folly::exception_wrapper processFirstResponse()

in thrift/lib/cpp2/async/RocketClientChannel.cpp [221:312]


FOLLY_NODISCARD folly::exception_wrapper processFirstResponse(
    ResponseRpcMetadata& metadata,
    std::unique_ptr<folly::IOBuf>& payload,
    Handler& handler) {
  if (auto payloadMetadataRef = metadata.payloadMetadata_ref()) {
    const auto isProxiedResponse =
        metadata.proxiedPayloadMetadata_ref().has_value();

    switch (payloadMetadataRef->getType()) {
      case PayloadMetadata::responseMetadata:
        payload = handler.handleReply(std::move(payload));
        break;
      case PayloadMetadata::exceptionMetadata: {
        auto& exceptionMetadataBase =
            payloadMetadataRef->get_exceptionMetadata();
        auto otherMetadataRef = metadata.otherMetadata_ref();
        if (!otherMetadataRef) {
          otherMetadataRef.emplace();
        }
        auto exceptionNameRef = exceptionMetadataBase.name_utf8_ref();
        auto exceptionWhatRef = exceptionMetadataBase.what_utf8_ref();
        if (auto exceptionMetadataRef = exceptionMetadataBase.metadata_ref()) {
          auto metaType = exceptionMetadataRef->getType();
          switch (metaType) {
            case PayloadExceptionMetadata::declaredException:
              if (exceptionNameRef) {
                (*otherMetadataRef)[isProxiedResponse ? "puex" : "uex"] =
                    *exceptionNameRef;
              }
              if (exceptionWhatRef) {
                (*otherMetadataRef)[isProxiedResponse ? "puexw" : "uexw"] =
                    *exceptionWhatRef;
              }
              if (auto dExClass = exceptionMetadataRef->declaredException_ref()
                                      ->errorClassification_ref()) {
                auto metaStr =
                    apache::thrift::detail::serializeErrorClassification(
                        *dExClass);
                (*otherMetadataRef)[std::string(detail::kHeaderExMeta)] =
                    std::move(metaStr);
              }
              payload = handler.handleReply(std::move(payload));
              break;
            case PayloadExceptionMetadata::proxyException:
              (*otherMetadataRef)
                  [isProxiedResponse ? "servicerouter:sr_error"
                                     : "servicerouter:sr_internal_error"] =
                      protocol::base64Encode(payload->coalesce());
              payload = handler.handleException(
                  TApplicationException(exceptionWhatRef.value_or("")));
              break;
            default:
              switch (metaType) {
                case PayloadExceptionMetadata::DEPRECATED_appClientException:
                  (*otherMetadataRef)[isProxiedResponse ? "pex" : "ex"] =
                      kAppClientErrorCode;
                  break;
                case PayloadExceptionMetadata::appUnknownException:
                  if (auto ec = exceptionMetadataRef->appUnknownException_ref()
                                    ->errorClassification_ref()) {
                    if (ec->blame_ref() &&
                        *ec->blame_ref() == ErrorBlame::CLIENT) {
                      (*otherMetadataRef)[isProxiedResponse ? "pex" : "ex"] =
                          kAppClientErrorCode;
                    }
                  }
                  break;
                default:;
              }

              if (exceptionNameRef) {
                (*otherMetadataRef)[isProxiedResponse ? "puex" : "uex"] =
                    *exceptionNameRef;
              }
              if (exceptionWhatRef) {
                (*otherMetadataRef)[isProxiedResponse ? "puexw" : "uexw"] =
                    *exceptionWhatRef;
              }
              payload = handler.handleException(
                  TApplicationException(exceptionWhatRef.value_or("")));
          }
        } else {
          return TApplicationException("Missing payload exception metadata");
        }
        break;
      }
      default:
        return TApplicationException("Invalid payload metadata type");
    }
  }
  return {};
}