
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/v3Here replace thenew_hcm_filterwith your filter name.
Inside this directory, create aBUILDfile and anew_hcm_filter.protofile. 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 therouterfilter.
Inside theNewHCMFiltermessage 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 thePassThroughFilterclass from thesource/extensions/filters/http/common/pass_through_filter.hheader file, if it’s meant to be used as both read and write filter.
In this filter we need to implement different functions from thePassThroughFilterclass 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 thedecodeHeadersfunction, and the header of the response packet from the upstream to downstream from theencodeHeadersfunction. Same fordecodeBodyandencodeBodyfunctions.
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 asNewHCMFilterConfigFactoryand inherit theFactoryBaseclass with specifying the template class name likeFactoryBas<envoy::extensions::filters::http::elastic_search::v3::NewHCMFilter>.
Inside this class, implement the Constructor and override thecreateFilterFactoryFromProtoTypedfunction to create and register the filter class. You may also override theisTerminalFilterByProtoTypedfunction and returntrueif 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/BUILDfile. Inside this file add the//envoy/extensions/filters/http/new_hcm_filter/v3:pkgin thev3_protos. - In the
envoy/source/extensions/extensions_build_config.bzlfile’sExtensionsdictionary, 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.yamlfile, 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.hfile, add the name for the new hcm filter inside theHttpFilterNameValuesclass 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.





