Overview
In Envoy, we may use HTTP Connection Manager(HCM) for the HTTP based communication. In this filter, we can add some extra sub-filters, which
are called HTTP filters.
In this blog, we’ll write about how to create a new HCM filter.
As there’s no official documentation about this, we can’t explain the design philosophy, we’ll only mention what changes
should be done and what should be added to implement a new HCM filter and make it workable.
Proto
At first, we need to build the proto file for the new HCM filter. For this, create a new directory likeenvoy/api/envoy/extensions/filters/http/new_hcm_filter/v3
Here replace thenew_hcm_filter
with your filter name.
Inside this directory, create aBUILD
file and anew_hcm_filter.proto
file. In the proto file we need to specify the package name which should be something likeenvoy.extensions.filters.http.new_hcm_filter.v3
, import the necessary files and define necessary options forgo_package
,java_package
, etc., and create a message something likeNewHCMFilter
. We may follow any other http filter’s proto file as a reference, for example we may follow therouter
filter.
Inside theNewHCMFilter
message we may add any required parameter we want to set from the Envoy configuration yaml. Update the build file accordingly to support the imported file, follow other hcm filters for any help. Most of them has similar kind of building dependency and structure.Filter Implementation
Now, we need to implement the filter class and its config class maintaining the HCM filter protocol.
Each HCM filter should inherit thePassThroughFilter
class from thesource/extensions/filters/http/common/pass_through_filter.h
header file, if it’s meant to be used as both read and write filter.
In this filter we need to implement different functions from thePassThroughFilter
class to have the functionalities of HCM filter. Some of them aredecodeHeaders
,decodeBody
,encodeHeaders
,encodeBody
, etc. We’ll get the header of a request packet going from the downstream to upstream in thedecodeHeaders
function, and the header of the response packet from the upstream to downstream from theencodeHeaders
function. Same fordecodeBody
andencodeBody
functions.
In the config file, we need to implement a FilterConfigFactory class that will be responsible to register the new filter in the filter chain. Let’s name this class asNewHCMFilterConfigFactory
and inherit theFactoryBase
class with specifying the template class name likeFactoryBas<envoy::extensions::filters::http::elastic_search::v3::NewHCMFilter>
.
Inside this class, implement the Constructor and override thecreateFilterFactoryFromProtoTyped
function to create and register the filter class. You may also override theisTerminalFilterByProtoTyped
function and returntrue
if the filter is a terminal filter. By default, it is false if you don’t implement. A terminal filter is a filter which must be at the end of the filter chain. Generally, a filter shouldn’t be a terminal filter.
For detailed understanding you may follow other HCM Filter’s code as reference. Specially for the config part.Adding References
To make it completely workable, we need to add the reference of the new filter in some places. Here are the files where we need to add the new filter:- Add the proto build package in the
envoy/api/BUILD
file. Inside this file add the//envoy/extensions/filters/http/new_hcm_filter/v3:pkg
in thev3_protos
. - In the
envoy/source/extensions/extensions_build_config.bzl
file’sExtensions
dictionary, add teh new hcm filter maintaining the format"envoy.filters.http.elastic_search": "//source/extensions/filters/http/elastic_search_filter:elastic_search_config"
. - in the
source/extensions/extensions_metadata.yaml
file, insert the metadata for the new hcm filter maintaining the format:\
envoy.filters.http.new_hcm_filter: categories: - envoy.filters.http security_posture: robust_to_untrusted_downstream status: stable type_urls: - envoy.extensions.filters.http.new_hcm_filter.v3.NewHCMFilter
- In the
source/extensions/filters/http/well_known_names.h
file, add the name for the new hcm filter inside theHttpFilterNameValues
class as a const string.
Example Format:const std::string NewHCMFilter = "envoy.filters.http.new_hcm_filter"
.
- Add the proto build package in the
Example config yaml
http_filters:
- name: envoy.filters.http.new_hcm_filter
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.new_hcm_filter.v3.NewHCMFilter
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
Conclusion
As Envoy doesn’t have any official documentation about creating a new HCM filter till now, the best way is to follow the other implemented
HCM filters as reference and maintaining their naming and structural formats.
In this blog we tried to sum up the mandatory changes that needs to be done to implement a new HCM filter and add it with the filter chain. This might change with time
if the envoy team changes their basic structure. But you might still get help from this.