in pilot/pkg/networking/core/v1alpha3/envoyfilter/listener_patch.go [410:528]
func patchHTTPFilters(patchContext networking.EnvoyFilter_PatchContext,
patches map[networking.EnvoyFilter_ApplyTo][]*model.EnvoyFilterConfigPatchWrapper,
listener *xdslistener.Listener, fc *xdslistener.FilterChain, filter *xdslistener.Filter) {
httpconn := &hcm.HttpConnectionManager{}
if filter.GetTypedConfig() != nil {
if err := filter.GetTypedConfig().UnmarshalTo(httpconn); err != nil {
return
// todo: figure out a non noisy logging option here
// as this loop will be called very frequently
}
}
for _, lp := range patches[networking.EnvoyFilter_HTTP_FILTER] {
applied := false
if !commonConditionMatch(patchContext, lp) ||
!listenerMatch(listener, lp) ||
!filterChainMatch(listener, fc, lp) ||
!networkFilterMatch(filter, lp) {
IncrementEnvoyFilterMetric(lp.Key(), HttpFilter, false)
continue
}
if lp.Operation == networking.EnvoyFilter_Patch_ADD {
applied = true
httpconn.HttpFilters = append(httpconn.HttpFilters, proto.Clone(lp.Value).(*hcm.HttpFilter))
} else if lp.Operation == networking.EnvoyFilter_Patch_INSERT_FIRST {
httpconn.HttpFilters = append([]*hcm.HttpFilter{proto.Clone(lp.Value).(*hcm.HttpFilter)}, httpconn.HttpFilters...)
} else if lp.Operation == networking.EnvoyFilter_Patch_INSERT_AFTER {
// Insert after without a filter match is same as ADD in the end
if !hasHTTPFilterMatch(lp) {
httpconn.HttpFilters = append(httpconn.HttpFilters, proto.Clone(lp.Value).(*hcm.HttpFilter))
continue
}
// find the matching filter first
insertPosition := -1
for i := 0; i < len(httpconn.HttpFilters); i++ {
if httpFilterMatch(httpconn.HttpFilters[i], lp) {
insertPosition = i + 1
break
}
}
if insertPosition == -1 {
continue
}
applied = true
clonedVal := proto.Clone(lp.Value).(*hcm.HttpFilter)
httpconn.HttpFilters = append(httpconn.HttpFilters, clonedVal)
if insertPosition < len(httpconn.HttpFilters)-1 {
copy(httpconn.HttpFilters[insertPosition+1:], httpconn.HttpFilters[insertPosition:])
httpconn.HttpFilters[insertPosition] = clonedVal
}
} else if lp.Operation == networking.EnvoyFilter_Patch_INSERT_BEFORE {
// insert before without a filter match is same as insert in the beginning
if !hasHTTPFilterMatch(lp) {
httpconn.HttpFilters = append([]*hcm.HttpFilter{proto.Clone(lp.Value).(*hcm.HttpFilter)}, httpconn.HttpFilters...)
continue
}
// find the matching filter first
insertPosition := -1
for i := 0; i < len(httpconn.HttpFilters); i++ {
if httpFilterMatch(httpconn.HttpFilters[i], lp) {
insertPosition = i
break
}
}
if insertPosition == -1 {
continue
}
applied = true
clonedVal := proto.Clone(lp.Value).(*hcm.HttpFilter)
httpconn.HttpFilters = append(httpconn.HttpFilters, clonedVal)
copy(httpconn.HttpFilters[insertPosition+1:], httpconn.HttpFilters[insertPosition:])
httpconn.HttpFilters[insertPosition] = clonedVal
} else if lp.Operation == networking.EnvoyFilter_Patch_REPLACE {
if !hasHTTPFilterMatch(lp) {
continue
}
// find the matching filter first
replacePosition := -1
for i := 0; i < len(httpconn.HttpFilters); i++ {
if httpFilterMatch(httpconn.HttpFilters[i], lp) {
replacePosition = i
break
}
}
if replacePosition == -1 {
log.Debugf("EnvoyFilter patch %v is not applied because no matching HTTP filter found.", lp)
continue
}
applied = true
clonedVal := proto.Clone(lp.Value).(*hcm.HttpFilter)
httpconn.HttpFilters[replacePosition] = clonedVal
}
IncrementEnvoyFilterMetric(lp.Key(), HttpFilter, applied)
}
removedFilters := sets.Set{}
for _, httpFilter := range httpconn.HttpFilters {
if patchHTTPFilter(patchContext, patches, listener, fc, filter, httpFilter) {
removedFilters.Insert(httpFilter.Name)
}
}
if len(removedFilters) > 0 {
tempArray := make([]*hcm.HttpFilter, 0, len(httpconn.HttpFilters)-len(removedFilters))
for _, filter := range httpconn.HttpFilters {
if removedFilters.Contains(filter.Name) {
continue
}
tempArray = append(tempArray, filter)
}
httpconn.HttpFilters = tempArray
}
if filter.GetTypedConfig() != nil {
// convert to any type
filter.ConfigType = &xdslistener.Filter_TypedConfig{TypedConfig: util.MessageToAny(httpconn)}
}
}