Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

header: getting rid of exception-throwing behaviors in header files [the rest] #12611

Merged
merged 19 commits into from
Aug 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions source/common/protobuf/utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,16 @@ ProtoValidationException::ProtoValidationException(const std::string& validation
ENVOY_LOG_MISC(debug, "Proto validation error; throwing {}", what());
}

void ProtoExceptionUtil::throwMissingFieldException(const std::string& field_name,
const Protobuf::Message& message) {
throw MissingFieldException(field_name, message);
}

void ProtoExceptionUtil::throwProtoValidationException(const std::string& validation_error,
const Protobuf::Message& message) {
throw ProtoValidationException(validation_error, message);
}

size_t MessageUtil::hash(const Protobuf::Message& message) {
std::string text_format;

Expand Down
64 changes: 47 additions & 17 deletions source/common/protobuf/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@

// Obtain the value of a wrapped field (e.g. google.protobuf.UInt32Value) if set. Otherwise, throw
// a MissingFieldException.
#define PROTOBUF_GET_WRAPPED_REQUIRED(message, field_name) \
((message).has_##field_name() ? (message).field_name().value() \
: throw MissingFieldException(#field_name, (message)))

#define PROTOBUF_GET_WRAPPED_REQUIRED(message, field_name) \
([](const auto& msg) { \
if (!msg.has_##field_name()) { \
::Envoy::ProtoExceptionUtil::throwMissingFieldException(#field_name, msg); \
} \
return msg.field_name().value(); \
}((message)))
// Obtain the milliseconds value of a google.protobuf.Duration field if set. Otherwise, return the
// default value.
#define PROTOBUF_GET_MS_OR_DEFAULT(message, field_name, default_value) \
Expand All @@ -48,14 +52,22 @@
// Obtain the milliseconds value of a google.protobuf.Duration field if set. Otherwise, throw a
// MissingFieldException.
#define PROTOBUF_GET_MS_REQUIRED(message, field_name) \
((message).has_##field_name() ? DurationUtil::durationToMilliseconds((message).field_name()) \
: throw MissingFieldException(#field_name, (message)))
([](const auto& msg) { \
if (!msg.has_##field_name()) { \
::Envoy::ProtoExceptionUtil::throwMissingFieldException(#field_name, msg); \
} \
return DurationUtil::durationToMilliseconds(msg.field_name()); \
}((message)))

// Obtain the seconds value of a google.protobuf.Duration field if set. Otherwise, throw a
// MissingFieldException.
#define PROTOBUF_GET_SECONDS_REQUIRED(message, field_name) \
((message).has_##field_name() ? DurationUtil::durationToSeconds((message).field_name()) \
: throw MissingFieldException(#field_name, (message)))
([](const auto& msg) { \
if (!msg.has_##field_name()) { \
::Envoy::ProtoExceptionUtil::throwMissingFieldException(#field_name, msg); \
} \
return DurationUtil::durationToSeconds(msg.field_name()); \
}((message)))

namespace Envoy {
namespace ProtobufPercentHelper {
Expand Down Expand Up @@ -90,10 +102,13 @@ uint64_t fractionalPercentDenominatorToInt(
// @param field_name supplies the field name in the message.
// @param default_value supplies the default if the field is not present.
#define PROTOBUF_PERCENT_TO_DOUBLE_OR_DEFAULT(message, field_name, default_value) \
(!std::isnan((message).field_name().value()) \
? (message).has_##field_name() ? (message).field_name().value() : default_value \
: throw EnvoyException(fmt::format("Value not in the range of 0..100 range.")))

([](const auto& msg) -> double { \
if (std::isnan(msg.field_name().value())) { \
::Envoy::ExceptionUtil::throwEnvoyException( \
fmt::format("Value not in the range of 0..100 range.")); \
} \
return (msg).has_##field_name() ? (msg).field_name().value() : default_value; \
}((message)))
// Convert an envoy::type::v3::Percent to a rounded integer or a default.
// @param message supplies the proto message containing the field.
// @param field_name supplies the field name in the message.
Expand All @@ -104,11 +119,15 @@ uint64_t fractionalPercentDenominatorToInt(
// Issue: https://github.com/envoyproxy/protoc-gen-validate/issues/85
#define PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(message, field_name, max_value, \
default_value) \
(!std::isnan((message).field_name().value()) \
? (message).has_##field_name() \
? ProtobufPercentHelper::convertPercent((message).field_name().value(), max_value) \
: ProtobufPercentHelper::checkAndReturnDefault(default_value, max_value) \
: throw EnvoyException(fmt::format("Value not in the range of 0..100 range.")))
([](const auto& msg) { \
if (std::isnan(msg.field_name().value())) { \
::Envoy::ExceptionUtil::throwEnvoyException( \
fmt::format("Value not in the range of 0..100 range.")); \
} \
return (msg).has_##field_name() \
? ProtobufPercentHelper::convertPercent((msg).field_name().value(), max_value) \
: ProtobufPercentHelper::checkAndReturnDefault(default_value, max_value); \
}((message)))

namespace Envoy {

Expand Down Expand Up @@ -185,6 +204,17 @@ class ProtoValidationException : public EnvoyException {
ProtoValidationException(const std::string& validation_error, const Protobuf::Message& message);
};

/**
* utility functions to call when throwing exceptions in header files
*/
class ProtoExceptionUtil {
public:
static void throwMissingFieldException(const std::string& field_name,
const Protobuf::Message& message);
static void throwProtoValidationException(const std::string& validation_error,
const Protobuf::Message& message);
};

class MessageUtil {
public:
// std::hash
Expand Down Expand Up @@ -256,7 +286,7 @@ class MessageUtil {

std::string err;
if (!Validate(message, &err)) {
throw ProtoValidationException(err, API_RECOVER_ORIGINAL(message));
ProtoExceptionUtil::throwProtoValidationException(err, API_RECOVER_ORIGINAL(message));
}
}

Expand Down
1 change: 1 addition & 0 deletions source/extensions/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ envoy_cc_library(
"//include/envoy/runtime:runtime_interface",
"//source/common/common:documentation_url_lib",
"//source/common/common:minimal_logger_lib",
"//source/common/common:utility_lib",
],
)
4 changes: 3 additions & 1 deletion source/extensions/common/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "common/common/documentation_url.h"
#include "common/common/logger.h"
#include "common/common/utility.h"

namespace Envoy {
namespace Extensions {
Expand Down Expand Up @@ -92,7 +93,8 @@ class ExtensionNameUtil {
return;
}

throw EnvoyException(fatalMessage(extension_type, deprecated_name, canonical_name));
ExceptionUtil::throwEnvoyException(
fatalMessage(extension_type, deprecated_name, canonical_name));
}

private:
Expand Down
1 change: 1 addition & 0 deletions source/extensions/filters/network/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ envoy_cc_library(
visibility = ["//visibility:public"],
deps = [
"//include/envoy/server:filter_config_interface",
"//source/extensions/common:utility_lib",
],
)

Expand Down
5 changes: 4 additions & 1 deletion source/extensions/filters/network/common/factory_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "envoy/server/transport_socket_config.h"
#include "envoy/upstream/upstream.h"

#include "common/common/utility.h"

namespace Envoy {
namespace Extensions {
namespace NetworkFilters {
Expand Down Expand Up @@ -56,7 +58,8 @@ class FactoryBase : public Server::Configuration::NamedNetworkFilterConfigFactor
virtual Upstream::ProtocolOptionsConfigConstSharedPtr
createProtocolOptionsTyped(const ProtocolOptionsProto&,
Server::Configuration::ProtocolOptionsFactoryContext&) {
throw EnvoyException(fmt::format("filter {} does not support protocol options", name_));
ExceptionUtil::throwEnvoyException(
fmt::format("filter {} does not support protocol options", name_));
}

const std::string name_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "envoy/common/exception.h"

#include "common/common/utility.h"

#include "extensions/filters/network/dubbo_proxy/filters/filter.h"
#include "extensions/filters/network/dubbo_proxy/metadata.h"
#include "extensions/filters/network/dubbo_proxy/protocol.h"
Expand Down Expand Up @@ -32,7 +34,7 @@ struct AppExceptionBase : public EnvoyException,
metadata.setResponseStatus<T>(status_);
metadata.setMessageType(MessageType::Response);
if (!protocol.encode(buffer, metadata, what(), response_type_)) {
throw EnvoyException("Failed to encode local reply message");
ExceptionUtil::throwEnvoyException("Failed to encode local reply message");
}

return ResponseType::Exception;
Expand Down
12 changes: 8 additions & 4 deletions source/extensions/filters/network/kafka/serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "common/common/byte_order.h"
#include "common/common/fmt.h"
#include "common/common/utility.h"

#include "extensions/filters/network/kafka/kafka_types.h"

Expand Down Expand Up @@ -206,7 +207,8 @@ class VarUInt32Deserializer : public Deserializer<uint32_t> {
offset_ += 7;
// Valid input can have at most 5 bytes.
if (offset_ >= 5 * 7) {
throw EnvoyException("VarUInt32 is too long (5th byte has highest bit set)");
ExceptionUtil::throwEnvoyException(
"VarUInt32 is too long (5th byte has highest bit set)");
}
}
}
Expand Down Expand Up @@ -463,7 +465,7 @@ class ArrayDeserializer : public Deserializer<std::vector<typename DeserializerT
if (required_ >= 0) {
children_ = std::vector<DeserializerType>(required_);
} else {
throw EnvoyException(absl::StrCat("invalid ARRAY length: ", required_));
ExceptionUtil::throwEnvoyException(absl::StrCat("invalid ARRAY length: ", required_));
}
length_consumed_ = true;
}
Expand Down Expand Up @@ -542,7 +544,8 @@ class CompactArrayDeserializer
if (required >= 1) {
children_ = std::vector<DeserializerType>(required - 1);
} else {
throw EnvoyException(absl::StrCat("invalid COMPACT_ARRAY length: ", required));
ExceptionUtil::throwEnvoyException(
absl::StrCat("invalid COMPACT_ARRAY length: ", required));
}
length_consumed_ = true;
}
Expand Down Expand Up @@ -625,7 +628,8 @@ class NullableArrayDeserializer
ready_ = true;
}
if (required_ < NULL_ARRAY_LENGTH) {
throw EnvoyException(fmt::format("invalid NULLABLE_ARRAY length: {}", required_));
ExceptionUtil::throwEnvoyException(
fmt::format("invalid NULLABLE_ARRAY length: {}", required_));
}

length_consumed_ = true;
Expand Down
3 changes: 2 additions & 1 deletion source/extensions/filters/network/mongo_proxy/bson_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "envoy/common/exception.h"

#include "common/common/logger.h"
#include "common/common/utility.h"

#include "extensions/filters/network/mongo_proxy/bson.h"

Expand Down Expand Up @@ -153,7 +154,7 @@ class FieldImpl : public Field {
private:
void checkType(Type type) const {
if (type_ != type) {
throw EnvoyException("invalid BSON field type cast");
ExceptionUtil::throwEnvoyException("invalid BSON field type cast");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "envoy/buffer/buffer.h"
#include "envoy/common/exception.h"

#include "common/common/utility.h"

#include "extensions/filters/network/thrift_proxy/thrift.h"

namespace Envoy {
Expand Down Expand Up @@ -36,9 +38,9 @@ class ThriftValue {
// and throw if the value's type doesn't match.
FieldType expected_field_type = Traits<T>::getFieldType();
if (expected_field_type != type()) {
throw EnvoyException(fmt::format("expected field type {}, got {}",
static_cast<int>(expected_field_type),
static_cast<int>(type())));
ExceptionUtil::throwEnvoyException(fmt::format("expected field type {}, got {}",
static_cast<int>(expected_field_type),
static_cast<int>(type())));
}

return *static_cast<const T*>(getValue());
Expand Down