func patchHTTPFilters()

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)}
	}
}