-
Notifications
You must be signed in to change notification settings - Fork 5.1k
http filters: less filter factory boilerplate #3109
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this direction, +1.
Server::Configuration::HttpFilterFactoryCb | ||
GzipFilterFactory::createFilterFactoryFromProto(const Protobuf::Message& proto_config, | ||
const std::string&, | ||
Server::Configuration::FactoryContext&) { | ||
return createFilter( | ||
GzipFilterConfigSharedPtr config = std::make_shared<GzipFilterConfig>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can FactoryBase
provide a method that hides the downcast? What I would do is have the GzipFilterFactory
implement createFilterFactoryFromTypedProto
, and pass in the already downcast variant from FactoryBase::createfilterFactoryFromProto
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I can do something like that, but the validation all has to be done here of course. I will see what I can do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://github.com/envoyproxy/envoy/blob/master/include/envoy/grpc/async_client.h#L162 for an example of this pattern that I did for gRPC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this. It looks great; you just need to fix your comments I think.
My suggestion is not to expand this to other filters yet; there may be further ways to simplify. But IMO there's no need to get it perfect first as this a solid improvement.
return createFilter( | ||
MessageUtil::downcastAndValidate<const envoy::config::filter::http::gzip::v2::Gzip&>( | ||
proto_config)); | ||
GzipFilterConfigSharedPtr config = std::make_shared<GzipFilterConfig>(validate(proto_config)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a huge improvement and I think we should just move forward with this. I also wonder here what in this file is specific to gzip, and couldn't be supplied by the framework as a template default of some sort. But let's go with this and we can keep iterating after merge if we think there's more ways to factor out the boilerplate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference is to not partially do this, at least within a filter family. I would rather just do all of the HTTP filters so we don't leave things an an inconsistent state. Can we brainstorm additional ways to reduce boilerplate now?
The only thing that comes to mind is to have the base class which implements the functions, but then accepts lambdas in the constructors. It's possible this would git rid of some more code? Not sure how much of an improvement that would be though.
Server::Configuration::FactoryContext&) { | ||
NOT_IMPLEMENTED; | ||
} | ||
|
||
Server::Configuration::HttpFilterFactoryCb | ||
GzipFilterFactory::createFilterFactoryFromProto(const Protobuf::Message& proto_config, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would still argue for the typed vs. untyped variants and having createFilterFactoryFromProto
defined in the superclass, with the typed variant here. This is cleaner, it saves basically a line of code and only exposes a typed interface to the subclass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I don't think I fully understood what you were asking for. I think I get it now. Will update.
Signed-off-by: Matt Klein <mklein@lyft.com>
d7dd9c3
to
61d41f5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach LGTM, will take another pass when out of WIP status.
FactoryBase(const std::string& name) : name_(name) {} | ||
|
||
private: | ||
virtual Server::Configuration::HttpFilterFactoryCb |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be protected rather than private?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
technically it can be private as it's only called by this class. Derived classes can override private functions. With that said, it doesn't matter to me one way or the other.
I'm going to hold on this till next week when the various filter config stuff has landed as I think I will be able to clean up some of that also. |
@mattklein123 if you want to pick this up again I can take another look. Once you merge master I want to patch in and play with the code so I can get a better feel. |
@jmarantz was planning on getting back to this, but also very happy to hand it over. I will merge master tomorrow so you can take a look. |
Signed-off-by: Matt Klein <mklein@lyft.com>
@jmarantz I merged master and also updated the factory base class to take into account the new per-route filter config which is implemented for buffer filter. Let me know what you think and whether you want to fully take this PR over or just play with it. I would like to land the HTTP stuff this week if possible (trying to clear through my backlog after the conference). |
Signed-off-by: Matt Klein <mklein@lyft.com>
Signed-off-by: Matt Klein <mklein@lyft.com>
Signed-off-by: Matt Klein <mklein@lyft.com>
de16ba4
to
8330775
Compare
@@ -21,7 +21,7 @@ message HealthCheck { | |||
|
|||
// Specifies the incoming HTTP endpoint that should be considered the | |||
// health check endpoint. For example */healthcheck*. | |||
string endpoint = 2 [(validate.rules).string.min_bytes = 1, deprecated = true]; | |||
string endpoint = 2 [deprecated = true]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was exposed with improved testing via my changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is rad, some minor comments.
@@ -17,7 +16,7 @@ namespace Extensions { | |||
namespace HttpFilters { | |||
namespace BufferFilter { | |||
|
|||
Http::FilterFactoryCb BufferFilterConfigFactory::createFilter( | |||
Http::FilterFactoryCb BufferFilterFactory::createTypedFilterFactoryFromProto( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: for consistency with gRPC, maybe this should have Typed
as a suffix, same with per-route.
} | ||
|
||
ProtobufTypes::MessagePtr createEmptyConfigProto() override { | ||
return ProtobufTypes::MessagePtr{new ConfigProto()}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: std::make_unique
?
@@ -1,3 +1,5 @@ | |||
#include "envoy/config/filter/http/squash/v2/squash.pb.validate.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come we started to need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because now the factory has built-in validation which wasn't happening before in all cases and the include is only in the .cc file.
Signed-off-by: Matt Klein <mklein@lyft.com>
@htuch updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wh00t.
I want a quick feedback as to whether this direction is worth it or not. It makes the registration boilerplate marginally better. I'm not really sure what else can be easily done.
@jmarantz WDYT? Continue?
This is in reference to #2911