aibrix icon indicating copy to clipboard operation
aibrix copied to clipboard

Add external-filter in Header for advanced routing

Open rayne-Li opened this issue 1 month ago • 1 comments

🚀 Feature Description and Motivation

AFAIK currently aibrix-gateway-plugins use pod.Label model.aibrix.ai/name filtering pods in cluster, I want to filter pods besides that, by using external filter in header or somewhere

Use Case

my cloud-edge openyurt k8s cluster need filter pods by nodepools, which i usually label pods like: node-pool:a or other topo-types labels i need by adding external-filters in headers, i can filter pod in exact area or for some tenant

Proposed Solution

  1. add external-filter(k8s label-selector type string) in selectTargetPod in gateway.go
// gateway.go
func (s *Server) selectTargetPod(ctx *types.RoutingContext, pods types.PodList, externalFilterExpr string) (string, error) {
	// ......

	// filter pod by header ext-filter
	// k8s labelSelector format, eg: "k=v"、"env in (prod,stg)"
	if externalFilterExpr != "" {
		sel, err := labels.Parse(externalFilterExpr)
		if err != nil {
			return "", err
		}
		out := make([]*corev1.Pod, 0, len(readyPods))
		for _, p := range readyPods {
			klog.V(3).InfoS("filtering pod", "pod", p.Name)
			if sel.Matches(labels.Set(p.Labels)) {
				out = append(out, p)
				klog.V(3).InfoS("filter passed", "pod", p.Name)
			}
		}
		readyPods = out
	}

	// ......

	return router.Route(ctx, &utils.PodArray{Pods: readyPods})
}
  1. get filter from header
// pkg/plugins/gateway/gateway_req_body.go line:78
		// external filter in header
		externalFilter := routingCtx.ReqHeaders[HeaderExternalFilter]
		klog.InfoS("found external filter", "filter", externalFilter)
		targetPodIP, err := s.selectTargetPod(routingCtx, podsArr, externalFilter)
  1. handle that header
// pkg/plugins/gateway/gateway_req_headers.go
func (s *Server) HandleRequestHeaders(ctx context.Context, requestID string, req *extProcPb.ProcessingRequest) (*extProcPb.ProcessingResponse, utils.User, int64, *types.RoutingContext) {
         // ......
	for _, n := range h.RequestHeaders.Headers.Headers {
		if strings.ToLower(n.Key) == "user" {
			username = string(n.RawValue)
		}
		if strings.ToLower(n.Key) == ":path" {
			requestPath = string(n.RawValue)
		}
		if strings.ToLower(n.Key) == "authorization" {
			reqHeaders[n.Key] = string(n.RawValue)
		}
                 // add that
		if strings.ToLower(n.Key) == HeaderExternalFilter {
			reqHeaders[n.Key] = string(n.RawValue)
		}
		klog.InfoS("header", "key", n.Key, "value", string(n.RawValue))
	}

i will add my PR below

rayne-Li avatar Nov 26 '25 08:11 rayne-Li

this looks like a very reasonable requirements. thanks for driving the efforts!

Jeffwan avatar Nov 27 '25 07:11 Jeffwan