diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go
index 89b6804a2ba..3069ef5cc50 100644
--- a/internal/gatewayapi/backendtrafficpolicy.go
+++ b/internal/gatewayapi/backendtrafficpolicy.go
@@ -14,10 +14,10 @@ import (
 	"strings"
 
 	perr "github.com/pkg/errors"
-	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/sets"
+	"k8s.io/utils/ptr"
 	gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
@@ -32,14 +32,14 @@ const (
 	MaxConsistentHashTableSize = 5000011 // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-maglevlbconfig
 )
 
-func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv1a1.BackendTrafficPolicy,
+func (t *Translator) ProcessBackendTrafficPolicies(resources *resource.Resources,
 	gateways []*GatewayContext,
 	routes []RouteContext,
 	xdsIR resource.XdsIRMap,
-	configMaps []*corev1.ConfigMap,
 ) []*egv1a1.BackendTrafficPolicy {
 	res := []*egv1a1.BackendTrafficPolicy{}
 
+	backendTrafficPolicies := resources.BackendTrafficPolicies
 	// Sort based on timestamp
 	sort.Slice(backendTrafficPolicies, func(i, j int) bool {
 		return backendTrafficPolicies[i].CreationTimestamp.Before(&(backendTrafficPolicies[j].CreationTimestamp))
@@ -130,7 +130,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv
 				}
 
 				// Set conditions for translation error if it got any
-				if err := t.translateBackendTrafficPolicyForRoute(policy, route, xdsIR, configMaps); err != nil {
+				if err := t.translateBackendTrafficPolicyForRoute(policy, route, xdsIR, resources); err != nil {
 					status.SetTranslationErrorForPolicyAncestors(&policy.Status,
 						ancestorRefs,
 						t.GatewayControllerName,
@@ -184,7 +184,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv
 				}
 
 				// Set conditions for translation error if it got any
-				if err := t.translateBackendTrafficPolicyForGateway(policy, currTarget, gateway, xdsIR, configMaps); err != nil {
+				if err := t.translateBackendTrafficPolicyForGateway(policy, currTarget, gateway, xdsIR, resources); err != nil {
 					status.SetTranslationErrorForPolicyAncestors(&policy.Status,
 						ancestorRefs,
 						t.GatewayControllerName,
@@ -288,7 +288,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(
 	policy *egv1a1.BackendTrafficPolicy,
 	route RouteContext,
 	xdsIR resource.XdsIRMap,
-	configMaps []*corev1.ConfigMap,
+	resources *resource.Resources,
 ) error {
 	var (
 		rl        *ir.RateLimit
@@ -349,7 +349,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(
 		errs = errors.Join(errs, err)
 	}
 
-	if ro, err = buildResponseOverride(policy, configMaps); err != nil {
+	if ro, err = buildResponseOverride(policy, resources); err != nil {
 		err = perr.WithMessage(err, "ResponseOverride")
 		errs = errors.Join(errs, err)
 	}
@@ -392,8 +392,8 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(
 				if strings.HasPrefix(r.Name, prefix) {
 					if errs != nil {
 						// Return a 500 direct response
-						r.DirectResponse = &ir.DirectResponse{
-							StatusCode: 500,
+						r.DirectResponse = &ir.CustomResponse{
+							StatusCode: ptr.To(uint32(500)),
 						}
 						continue
 					}
@@ -438,7 +438,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
 	target gwapiv1a2.LocalPolicyTargetReferenceWithSectionName,
 	gateway *GatewayContext,
 	xdsIR resource.XdsIRMap,
-	configMaps []*corev1.ConfigMap,
+	resources *resource.Resources,
 ) error {
 	var (
 		rl        *ir.RateLimit
@@ -491,7 +491,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
 		err = perr.WithMessage(err, "HTTP2")
 		errs = errors.Join(errs, err)
 	}
-	if ro, err = buildResponseOverride(policy, configMaps); err != nil {
+	if ro, err = buildResponseOverride(policy, resources); err != nil {
 		err = perr.WithMessage(err, "ResponseOverride")
 		errs = errors.Join(errs, err)
 	}
@@ -561,8 +561,8 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(
 
 			if errs != nil {
 				// Return a 500 direct response
-				r.DirectResponse = &ir.DirectResponse{
-					StatusCode: 500,
+				r.DirectResponse = &ir.CustomResponse{
+					StatusCode: ptr.To(uint32(500)),
 				}
 				continue
 			}
@@ -864,7 +864,7 @@ func makeIrTriggerSet(in []egv1a1.TriggerEnum) []ir.TriggerEnum {
 	return irTriggers
 }
 
-func buildResponseOverride(policy *egv1a1.BackendTrafficPolicy, configMaps []*corev1.ConfigMap) (*ir.ResponseOverride, error) {
+func buildResponseOverride(policy *egv1a1.BackendTrafficPolicy, resources *resource.Resources) (*ir.ResponseOverride, error) {
 	if len(policy.Spec.ResponseOverride) == 0 {
 		return nil, nil
 	}
@@ -894,33 +894,10 @@ func buildResponseOverride(policy *egv1a1.BackendTrafficPolicy, configMaps []*co
 			ContentType: ro.Response.ContentType,
 		}
 
-		if ro.Response.Body.Type != nil && *ro.Response.Body.Type == egv1a1.ResponseValueTypeValueRef {
-			foundCM := false
-			for _, cm := range configMaps {
-				if cm.Namespace == policy.Namespace && cm.Name == string(ro.Response.Body.ValueRef.Name) {
-					body, dataOk := cm.Data["response.body"]
-					switch {
-					case dataOk:
-						response.Body = body
-					case len(cm.Data) > 0: // Fallback to the first key if response.body is not found
-						for _, value := range cm.Data {
-							body = value
-							break
-						}
-						response.Body = body
-					default:
-						return nil, fmt.Errorf("can't find the key response.body in the referenced configmap %s", ro.Response.Body.ValueRef.Name)
-					}
-
-					foundCM = true
-					break
-				}
-			}
-			if !foundCM {
-				return nil, fmt.Errorf("can't find the referenced configmap %s", ro.Response.Body.ValueRef.Name)
-			}
-		} else {
-			response.Body = *ro.Response.Body.Inline
+		var err error
+		response.Body, err = getCustomResponseBody(ro.Response.Body, resources, policy.Namespace)
+		if err != nil {
+			return nil, err
 		}
 
 		rules = append(rules, ir.ResponseOverrideRule{
@@ -935,6 +912,34 @@ func buildResponseOverride(policy *egv1a1.BackendTrafficPolicy, configMaps []*co
 	}, nil
 }
 
+func getCustomResponseBody(body egv1a1.CustomResponseBody, resources *resource.Resources, policyNs string) (*string, error) {
+	if body.Type != nil && *body.Type == egv1a1.ResponseValueTypeValueRef {
+		cm := resources.GetConfigMap(policyNs, string(body.ValueRef.Name))
+		if cm != nil {
+			b, dataOk := cm.Data["response.body"]
+			switch {
+			case dataOk:
+				return &b, nil
+			case len(cm.Data) > 0: // Fallback to the first key if response.body is not found
+				for _, value := range cm.Data {
+					b = value
+					break
+				}
+				return &b, nil
+			default:
+				return nil, fmt.Errorf("can't find the key response.body in the referenced configmap %s", body.ValueRef.Name)
+			}
+
+		} else {
+			return nil, fmt.Errorf("can't find the referenced configmap %s", body.ValueRef.Name)
+		}
+	} else if body.Inline != nil {
+		return body.Inline, nil
+	}
+
+	return nil, nil
+}
+
 func defaultResponseOverrideRuleName(policy *egv1a1.BackendTrafficPolicy, index int) string {
 	return fmt.Sprintf(
 		"%s/responseoverride/rule/%s",
diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go
index 5e61f2eb3aa..4abc9a69046 100644
--- a/internal/gatewayapi/envoyextensionpolicy.go
+++ b/internal/gatewayapi/envoyextensionpolicy.go
@@ -324,8 +324,8 @@ func (t *Translator) translateEnvoyExtensionPolicyForRoute(
 					if strings.HasPrefix(r.Name, prefix) {
 						// return 500 and do not configure EnvoyExtensions in this case
 						if errs != nil {
-							r.DirectResponse = &ir.DirectResponse{
-								StatusCode: 500,
+							r.DirectResponse = &ir.CustomResponse{
+								StatusCode: ptr.To(uint32(500)),
 							}
 							continue
 						}
@@ -386,8 +386,8 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway(
 
 			// return 500 and do not configure EnvoyExtensions in this case
 			if errs != nil {
-				r.DirectResponse = &ir.DirectResponse{
-					StatusCode: 500,
+				r.DirectResponse = &ir.CustomResponse{
+					StatusCode: ptr.To(uint32(500)),
 				}
 				continue
 			}
diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go
index e969b7365fc..68bf84b33c2 100644
--- a/internal/gatewayapi/filters.go
+++ b/internal/gatewayapi/filters.go
@@ -47,7 +47,7 @@ type HTTPFiltersContext struct {
 
 // HTTPFilterIR contains the ir processing results.
 type HTTPFilterIR struct {
-	DirectResponse   *ir.DirectResponse
+	DirectResponse   *ir.CustomResponse
 	RedirectResponse *ir.Redirect
 
 	URLRewrite *ir.URLRewrite
@@ -785,8 +785,10 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec
 	filterNs := filterContext.Route.GetNamespace()
 
 	if string(extFilter.Kind) == egv1a1.KindHTTPRouteFilter {
+		found := false
 		for _, hrf := range resources.HTTPRouteFilters {
 			if hrf.Namespace == filterNs && hrf.Name == string(extFilter.Name) {
+				found = true
 				if hrf.Spec.URLRewrite != nil {
 
 					if filterContext.URLRewrite != nil {
@@ -846,7 +848,6 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec
 									filterContext.HTTPFilterIR.URLRewrite.Path = &ir.ExtendedHTTPPathModifier{
 										RegexMatchReplace: rmr,
 									}
-									return
 								}
 							} else { // no url rewrite
 								filterContext.HTTPFilterIR.URLRewrite = &ir.URLRewrite{
@@ -854,7 +855,6 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec
 										RegexMatchReplace: rmr,
 									},
 								}
-								return
 							}
 						}
 					}
@@ -887,22 +887,49 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec
 						if filterContext.HTTPFilterIR.URLRewrite != nil {
 							if filterContext.HTTPFilterIR.URLRewrite.Host == nil {
 								filterContext.HTTPFilterIR.URLRewrite.Host = hm
-								return
 							}
 						} else { // no url rewrite
 							filterContext.HTTPFilterIR.URLRewrite = &ir.URLRewrite{
 								Host: hm,
 							}
+						}
+					}
+
+				}
+
+				if hrf.Spec.DirectResponse != nil {
+					dr := &ir.CustomResponse{}
+					if hrf.Spec.DirectResponse.Body != nil {
+						var err error
+						if dr.Body, err = getCustomResponseBody(*hrf.Spec.DirectResponse.Body, resources, filterNs); err != nil {
+							t.processInvalidHTTPFilter(string(extFilter.Kind), filterContext, err)
 							return
 						}
 					}
 
+					if hrf.Spec.DirectResponse.StatusCode != nil {
+						dr.StatusCode = ptr.To(uint32(*hrf.Spec.DirectResponse.StatusCode))
+					} else {
+						dr.StatusCode = ptr.To(uint32(200))
+					}
+
+					if hrf.Spec.DirectResponse.ContentType != nil {
+						newHeader := ir.AddHeader{
+							Name:  "Content-Type",
+							Value: []string{*hrf.Spec.DirectResponse.ContentType},
+						}
+						filterContext.AddResponseHeaders = append(filterContext.AddResponseHeaders, newHeader)
+					}
+
+					filterContext.HTTPFilterIR.DirectResponse = dr
 				}
 			}
 		}
-		errMsg := fmt.Sprintf("Unable to translate HTTPRouteFilter: %s/%s", filterNs,
-			extFilter.Name)
-		t.processUnresolvedHTTPFilter(errMsg, filterContext)
+		if !found {
+			errMsg := fmt.Sprintf("Unable to translate HTTPRouteFilter: %s/%s", filterNs,
+				extFilter.Name)
+			t.processUnresolvedHTTPFilter(errMsg, filterContext)
+		}
 		return
 	}
 
@@ -993,8 +1020,8 @@ func (t *Translator) processUnresolvedHTTPFilter(errMsg string, filterContext *H
 		gwapiv1.RouteReasonUnsupportedValue,
 		errMsg,
 	)
-	filterContext.DirectResponse = &ir.DirectResponse{
-		StatusCode: 500,
+	filterContext.DirectResponse = &ir.CustomResponse{
+		StatusCode: ptr.To(uint32(500)),
 	}
 }
 
@@ -1009,8 +1036,8 @@ func (t *Translator) processUnsupportedHTTPFilter(filterType string, filterConte
 		gwapiv1.RouteReasonUnsupportedValue,
 		errMsg,
 	)
-	filterContext.DirectResponse = &ir.DirectResponse{
-		StatusCode: 500,
+	filterContext.DirectResponse = &ir.CustomResponse{
+		StatusCode: ptr.To(uint32(500)),
 	}
 }
 
@@ -1025,7 +1052,7 @@ func (t *Translator) processInvalidHTTPFilter(filterType string, filterContext *
 		gwapiv1.RouteReasonUnsupportedValue,
 		errMsg,
 	)
-	filterContext.DirectResponse = &ir.DirectResponse{
-		StatusCode: 500,
+	filterContext.DirectResponse = &ir.CustomResponse{
+		StatusCode: ptr.To(uint32(500)),
 	}
 }
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index f82158715a5..648aebaeb5c 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -238,8 +238,8 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
 		for _, ruleRoute := range ruleRoutes {
 			noValidBackends := ruleRoute.Destination == nil || ruleRoute.Destination.ToBackendWeights().Valid == 0
 			if noValidBackends && ruleRoute.Redirect == nil {
-				ruleRoute.DirectResponse = &ir.DirectResponse{
-					StatusCode: 500,
+				ruleRoute.DirectResponse = &ir.CustomResponse{
+					StatusCode: ptr.To(uint32(500)),
 				}
 			}
 			ruleRoute.IsHTTP2 = false
@@ -570,8 +570,8 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 		for _, ruleRoute := range ruleRoutes {
 			noValidBackends := ruleRoute.Destination == nil || ruleRoute.Destination.ToBackendWeights().Valid == 0
 			if noValidBackends && ruleRoute.Redirect == nil {
-				ruleRoute.DirectResponse = &ir.DirectResponse{
-					StatusCode: 500,
+				ruleRoute.DirectResponse = &ir.CustomResponse{
+					StatusCode: ptr.To(uint32(500)),
 				}
 			}
 			ruleRoute.IsHTTP2 = true
diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go
index c9289bbcfb3..302d5054507 100644
--- a/internal/gatewayapi/securitypolicy.go
+++ b/internal/gatewayapi/securitypolicy.go
@@ -406,8 +406,8 @@ func (t *Translator) translateSecurityPolicyForRoute(
 						}
 						if errs != nil {
 							// Return a 500 direct response to avoid unauthorized access
-							r.DirectResponse = &ir.DirectResponse{
-								StatusCode: 500,
+							r.DirectResponse = &ir.CustomResponse{
+								StatusCode: ptr.To(uint32(500)),
 							}
 						}
 					}
@@ -514,8 +514,8 @@ func (t *Translator) translateSecurityPolicyForGateway(
 			}
 			if errs != nil {
 				// Return a 500 direct response to avoid unauthorized access
-				r.DirectResponse = &ir.DirectResponse{
-					StatusCode: 500,
+				r.DirectResponse = &ir.CustomResponse{
+					StatusCode: ptr.To(uint32(500)),
 				}
 			}
 		}
diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go
index 0f518b71033..23e651b6c69 100644
--- a/internal/gatewayapi/translator.go
+++ b/internal/gatewayapi/translator.go
@@ -211,7 +211,7 @@ func (t *Translator) Translate(resources *resource.Resources) (*TranslateResult,
 
 	// Process BackendTrafficPolicies
 	backendTrafficPolicies := t.ProcessBackendTrafficPolicies(
-		resources.BackendTrafficPolicies, gateways, routes, xdsIR, resources.ConfigMaps)
+		resources, gateways, routes, xdsIR)
 
 	// Process SecurityPolicies
 	securityPolicies := t.ProcessSecurityPolicies(
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 00edaf21b57..e10a1ec2987 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -532,7 +532,20 @@ type CustomResponse struct {
 	ContentType *string `json:"contentType,omitempty"`
 
 	// Body of the Custom Response
-	Body string `json:"body"`
+	Body *string `json:"body,omitempty"`
+
+	// StatusCode will be used for the response's status code.
+	StatusCode *uint32 `json:"statusCode,omitempty"`
+}
+
+// Validate the fields within the CustomResponse structure
+func (r *CustomResponse) Validate() error {
+	var errs error
+	if status := r.StatusCode; status != nil && (*status > 599 || *status < 100) {
+		errs = errors.Join(errs, ErrDirectResponseStatusInvalid)
+	}
+
+	return errs
 }
 
 // HealthCheckSettings provides HealthCheck configuration on the HTTP/HTTPS listener.
@@ -625,7 +638,7 @@ type HTTPRoute struct {
 	// RemoveResponseHeaders defines a list of headers to be removed from response.
 	RemoveResponseHeaders []string `json:"removeResponseHeaders,omitempty" yaml:"removeResponseHeaders,omitempty"`
 	// Direct responses to be returned for this route. Takes precedence over Destinations and Redirect.
-	DirectResponse *DirectResponse `json:"directResponse,omitempty" yaml:"directResponse,omitempty"`
+	DirectResponse *CustomResponse `json:"directResponse,omitempty" yaml:"directResponse,omitempty"`
 	// Redirections to be returned for this route. Takes precedence over Destinations.
 	Redirect *Redirect `json:"redirect,omitempty" yaml:"redirect,omitempty"`
 	// Destination that requests to this HTTPRoute will be mirrored to
@@ -1361,23 +1374,6 @@ func (h AddHeader) Validate() error {
 	return errs
 }
 
-// DirectResponse holds the details for returning a body and status code for a route.
-// +k8s:deepcopy-gen=true
-type DirectResponse struct {
-	// StatusCode will be used for the direct response's status code.
-	StatusCode uint32 `json:"statusCode" yaml:"statusCode"`
-}
-
-// Validate the fields within the DirectResponse structure
-func (r DirectResponse) Validate() error {
-	var errs error
-	if status := r.StatusCode; status > 599 || status < 100 {
-		errs = errors.Join(errs, ErrDirectResponseStatusInvalid)
-	}
-
-	return errs
-}
-
 // URLRewrite holds the details for how to rewrite a request
 // +k8s:deepcopy-gen=true
 type URLRewrite struct {
diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go
index b4593152593..7a81491417d 100644
--- a/internal/ir/xds_test.go
+++ b/internal/ir/xds_test.go
@@ -254,8 +254,8 @@ var (
 		PathMatch: &StringMatch{
 			Exact: ptr.To("filter-error"),
 		},
-		DirectResponse: &DirectResponse{
-			StatusCode: uint32(500),
+		DirectResponse: &CustomResponse{
+			StatusCode: ptr.To(uint32(500)),
 		},
 	}
 
@@ -296,8 +296,8 @@ var (
 		PathMatch: &StringMatch{
 			Exact: ptr.To("redirect"),
 		},
-		DirectResponse: &DirectResponse{
-			StatusCode: uint32(799),
+		DirectResponse: &CustomResponse{
+			StatusCode: ptr.To(uint32(799)),
 		},
 	}
 
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index 111f2661377..9054f99854a 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -610,6 +610,16 @@ func (in *CustomResponse) DeepCopyInto(out *CustomResponse) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.Body != nil {
+		in, out := &in.Body, &out.Body
+		*out = new(string)
+		**out = **in
+	}
+	if in.StatusCode != nil {
+		in, out := &in.StatusCode, &out.StatusCode
+		*out = new(uint32)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResponse.
@@ -779,21 +789,6 @@ func (in *DestinationSetting) DeepCopy() *DestinationSetting {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *DirectResponse) DeepCopyInto(out *DirectResponse) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponse.
-func (in *DirectResponse) DeepCopy() *DirectResponse {
-	if in == nil {
-		return nil
-	}
-	out := new(DirectResponse)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *EnvoyExtensionFeatures) DeepCopyInto(out *EnvoyExtensionFeatures) {
 	*out = *in
@@ -1464,8 +1459,8 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
 	}
 	if in.DirectResponse != nil {
 		in, out := &in.DirectResponse, &out.DirectResponse
-		*out = new(DirectResponse)
-		**out = **in
+		*out = new(CustomResponse)
+		(*in).DeepCopyInto(*out)
 	}
 	if in.Redirect != nil {
 		in, out := &in.Redirect, &out.Redirect
diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go
index ac106a69f7e..d4681406454 100644
--- a/internal/provider/kubernetes/controller.go
+++ b/internal/provider/kubernetes/controller.go
@@ -1660,6 +1660,10 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M
 		return err
 	}
 
+	if err := addRouteFilterIndexers(ctx, mgr); err != nil {
+		return err
+	}
+
 	return nil
 }
 
diff --git a/internal/provider/kubernetes/filters.go b/internal/provider/kubernetes/filters.go
index 109c0314dd0..b322950cced 100644
--- a/internal/provider/kubernetes/filters.go
+++ b/internal/provider/kubernetes/filters.go
@@ -9,9 +9,13 @@ import (
 	"context"
 	"fmt"
 
+	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/types"
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
+	"github.com/envoyproxy/gateway/internal/gatewayapi/resource"
+	"github.com/envoyproxy/gateway/internal/utils"
 )
 
 func (r *gatewayAPIReconciler) getExtensionRefFilters(ctx context.Context) ([]unstructured.Unstructured, error) {
@@ -54,3 +58,37 @@ func (r *gatewayAPIReconciler) getHTTPRouteFilters(ctx context.Context) ([]egv1a
 
 	return httpFilterList.Items, nil
 }
+
+// processRouteFilterConfigMapRef adds the referenced ConfigMap in a HTTPRouteFilter
+// to the resourceTree
+func (r *gatewayAPIReconciler) processRouteFilterConfigMapRef(
+	ctx context.Context, filter *egv1a1.HTTPRouteFilter,
+	resourceMap *resourceMappings, resourceTree *resource.Resources,
+) {
+	if filter.Spec.DirectResponse != nil &&
+		filter.Spec.DirectResponse.Body.ValueRef != nil &&
+		string(filter.Spec.DirectResponse.Body.ValueRef.Kind) == resource.KindConfigMap {
+		configMap := new(corev1.ConfigMap)
+		err := r.client.Get(ctx,
+			types.NamespacedName{Namespace: filter.Namespace, Name: string(filter.Spec.DirectResponse.Body.ValueRef.Name)},
+			configMap)
+		// we don't return an error here, because we want to continue
+		// reconciling the rest of the HTTPRouteFilter despite that this
+		// reference is invalid.
+		// This HTTPRouteFilter will be marked as invalid in its status
+		// when translating to IR because the referenced configmap can't be
+		// found.
+		if err != nil {
+			r.log.Error(err,
+				"failed to process DirectResponse ValueRef for HTTPRouteFilter",
+				"filter", filter, "ValueRef", filter.Spec.DirectResponse.Body.ValueRef.Name)
+		}
+
+		resourceMap.allAssociatedNamespaces.Insert(filter.Namespace)
+		if !resourceMap.allAssociatedConfigMaps.Has(utils.NamespacedName(configMap).String()) {
+			resourceMap.allAssociatedConfigMaps.Insert(utils.NamespacedName(configMap).String())
+			resourceTree.ConfigMaps = append(resourceTree.ConfigMaps, configMap)
+			r.log.Info("processing ConfigMap", "namespace", filter.Namespace, "name", string(filter.Spec.DirectResponse.Body.ValueRef.Name))
+		}
+	}
+}
diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go
index 2ad12069f98..ab3c098961e 100644
--- a/internal/provider/kubernetes/indexers.go
+++ b/internal/provider/kubernetes/indexers.go
@@ -47,6 +47,7 @@ const (
 	secretEnvoyExtensionPolicyIndex  = "secretEnvoyExtensionPolicyIndex"
 	httpRouteFilterHTTPRouteIndex    = "httpRouteFilterHTTPRouteIndex"
 	configMapBtpIndex                = "configMapBtpIndex"
+	configMapHTTPRouteFilterIndex    = "configMapHTTPRouteFilterIndex"
 )
 
 func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error {
@@ -672,6 +673,35 @@ func configMapBtpIndexFunc(rawObj client.Object) []string {
 	return configMapReferences
 }
 
+// addRouteFilterIndexers adds indexing on HTTPRouteFilter, for ConfigMap objects that are
+// referenced in HTTPRouteFilter objects. This helps in querying for HTTPRouteFilters that are
+// affected by a particular ConfigMap CRUD.
+func addRouteFilterIndexers(ctx context.Context, mgr manager.Manager) error {
+	if err := mgr.GetFieldIndexer().IndexField(ctx, &egv1a1.HTTPRouteFilter{},
+		configMapHTTPRouteFilterIndex, configMapRouteFilterIndexFunc); err != nil {
+		return err
+	}
+	return nil
+}
+
+func configMapRouteFilterIndexFunc(rawObj client.Object) []string {
+	filter := rawObj.(*egv1a1.HTTPRouteFilter)
+	var configMapReferences []string
+	if filter.Spec.DirectResponse != nil &&
+		filter.Spec.DirectResponse.Body != nil &&
+		filter.Spec.DirectResponse.Body.ValueRef != nil {
+		if string(filter.Spec.DirectResponse.Body.ValueRef.Kind) == resource.KindConfigMap {
+			configMapReferences = append(configMapReferences,
+				types.NamespacedName{
+					Namespace: filter.Namespace,
+					Name:      string(filter.Spec.DirectResponse.Body.ValueRef.Name),
+				}.String(),
+			)
+		}
+	}
+	return configMapReferences
+}
+
 // addBtlsIndexers adds indexing on BackendTLSPolicy, for ConfigMap objects that are
 // referenced in BackendTLSPolicy objects. This helps in querying for BackendTLSPolicies that are
 // affected by a particular ConfigMap CRUD.
diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go
index bfdecbd6e24..ae4f63ef3e9 100644
--- a/internal/provider/kubernetes/predicates.go
+++ b/internal/provider/kubernetes/predicates.go
@@ -632,6 +632,18 @@ func (r *gatewayAPIReconciler) validateConfigMapForReconcile(obj client.Object)
 		return true
 	}
 
+	routeFilterList := &egv1a1.HTTPRouteFilterList{}
+	if err := r.client.List(context.Background(), routeFilterList, &client.ListOptions{
+		FieldSelector: fields.OneTermEqualSelector(configMapHTTPRouteFilterIndex, utils.NamespacedName(configMap).String()),
+	}); err != nil {
+		r.log.Error(err, "unable to find associated HTTPRouteFilter")
+		return false
+	}
+
+	if len(routeFilterList.Items) > 0 {
+		return true
+	}
+
 	return false
 }
 
diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go
index 74bc1312e58..dcc01631f3b 100644
--- a/internal/provider/kubernetes/routes.go
+++ b/internal/provider/kubernetes/routes.go
@@ -243,9 +243,11 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam
 	if err != nil {
 		return err
 	}
+
 	for i := range httpFilters {
 		filter := httpFilters[i]
 		resourceMap.httpRouteFilters[utils.GetNamespacedNameWithGroupKind(&filter)] = &filter
+		r.processRouteFilterConfigMapRef(ctx, &filter, resourceMap, resourceTree)
 	}
 
 	extensionRefFilters, err := r.getExtensionRefFilters(ctx)
diff --git a/internal/xds/translator/custom_response.go b/internal/xds/translator/custom_response.go
index 1d1bf3a5d2c..e5d48d21bfd 100644
--- a/internal/xds/translator/custom_response.go
+++ b/internal/xds/translator/custom_response.go
@@ -375,12 +375,13 @@ func (c *customResponse) buildStatusCodeCELMatcher(codeRange ir.StatusCodeRange)
 }
 
 func (c *customResponse) buildAction(r ir.ResponseOverrideRule) (*matcherv3.Matcher_OnMatch_Action, error) {
-	response := &policyv3.LocalResponsePolicy{
-		Body: &corev3.DataSource{
+	response := &policyv3.LocalResponsePolicy{}
+	if r.Response.Body != nil && *r.Response.Body != "" {
+		response.Body = &corev3.DataSource{
 			Specifier: &corev3.DataSource_InlineString{
-				InlineString: r.Response.Body,
+				InlineString: *r.Response.Body,
 			},
-		},
+		}
 	}
 
 	if r.Response.ContentType != nil && *r.Response.ContentType != "" {
diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go
index e1d790268dc..3750194fb16 100644
--- a/internal/xds/translator/route.go
+++ b/internal/xds/translator/route.go
@@ -440,8 +440,20 @@ func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite, pathMa
 	return routeAction
 }
 
-func buildXdsDirectResponseAction(res *ir.DirectResponse) *routev3.DirectResponseAction {
-	routeAction := &routev3.DirectResponseAction{Status: res.StatusCode}
+func buildXdsDirectResponseAction(res *ir.CustomResponse) *routev3.DirectResponseAction {
+	routeAction := &routev3.DirectResponseAction{}
+	if res.StatusCode != nil {
+		routeAction.Status = *res.StatusCode
+	}
+
+	if res.Body != nil && *res.Body != "" {
+		routeAction.Body = &corev3.DataSource{
+			Specifier: &corev3.DataSource_InlineString{
+				InlineString: *res.Body,
+			},
+		}
+	}
+
 	return routeAction
 }
 
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml
index e9cff901d3d..405c2372d91 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml
@@ -51,6 +51,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-endpoint-stats.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-endpoint-stats.yaml
index b5244667de9..2355c6504cf 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-endpoint-stats.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-endpoint-stats.yaml
@@ -47,6 +47,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-formatters.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-formatters.yaml
index 7c1024879d8..e4e088d349b 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-formatters.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-formatters.yaml
@@ -55,6 +55,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml
index fab193fe564..95b4971cd39 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml
@@ -55,6 +55,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-types.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-types.yaml
index d2458abfce9..b42a839f018 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-types.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-types.yaml
@@ -179,6 +179,3 @@ http:
             - endpoints:
                 - host: "1.2.3.4"
                   port: 50000
-        directResponse:
-          body: "Unknown custom filter type: UnsupportedType"
-          statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-without-format.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-without-format.yaml
index 40aef558e3e..90e9f0e0c9b 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-without-format.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-without-format.yaml
@@ -59,6 +59,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog.yaml
index 26f0f5663f8..5169bae040e 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog.yaml
@@ -68,6 +68,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/tracing-datadog.yaml b/internal/xds/translator/testdata/in/xds-ir/tracing-datadog.yaml
index 1cc60f85e0e..1ed5b3aef3c 100644
--- a/internal/xds/translator/testdata/in/xds-ir/tracing-datadog.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/tracing-datadog.yaml
@@ -44,6 +44,3 @@ http:
             - endpoints:
                 - host: "1.2.3.4"
                   port: 50000
-        directResponse:
-          body: "Unknown custom filter type: UnsupportedType"
-          statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/tracing-endpoint-stats.yaml b/internal/xds/translator/testdata/in/xds-ir/tracing-endpoint-stats.yaml
index b5ee8b57dd9..1d8c4b7a338 100644
--- a/internal/xds/translator/testdata/in/xds-ir/tracing-endpoint-stats.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/tracing-endpoint-stats.yaml
@@ -49,6 +49,3 @@ http:
             - endpoints:
                 - host: "1.2.3.4"
                   port: 50000
-        directResponse:
-          body: "Unknown custom filter type: UnsupportedType"
-          statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml b/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml
index 9b4e57fd74f..dded17dd193 100644
--- a/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/tracing-zipkin.yaml
@@ -50,6 +50,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/in/xds-ir/tracing.yaml b/internal/xds/translator/testdata/in/xds-ir/tracing.yaml
index 2bd8aff1b7d..b5cccf6dbab 100644
--- a/internal/xds/translator/testdata/in/xds-ir/tracing.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/tracing.yaml
@@ -68,6 +68,3 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
-    directResponse:
-      body: "Unknown custom filter type: UnsupportedType"
-      statusCode: 500
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-types.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-types.routes.yaml
index ff2210f8d50..084eabe4105 100644
--- a/internal/xds/translator/testdata/out/xds-ir/accesslog-types.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-types.routes.yaml
@@ -13,8 +13,10 @@
             sectionName: http
     name: envoy-gateway/gateway-1/http/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-without-format.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-without-format.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/accesslog-without-format.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-without-format.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/accesslog.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/accesslog.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.routes.yaml
index b214e8b05a3..d4a7fa5ae20 100644
--- a/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.routes.yaml
@@ -6,6 +6,8 @@
     name: first-listener/*
     routes:
     - directResponse:
+        body:
+          inlineString: 'Unknown custom filter type: UnsupportedType'
         status: 500
       match:
         prefix: /
diff --git a/internal/xds/translator/testdata/out/xds-ir/tracing-datadog.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing-datadog.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/tracing-datadog.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/tracing-datadog.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/tracing-endpoint-stats.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing-endpoint-stats.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/tracing-endpoint-stats.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/tracing-endpoint-stats.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/tracing-zipkin.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/internal/xds/translator/testdata/out/xds-ir/tracing.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing.routes.yaml
index b214e8b05a3..ea343799ac1 100644
--- a/internal/xds/translator/testdata/out/xds-ir/tracing.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/tracing.routes.yaml
@@ -5,8 +5,10 @@
     - '*'
     name: first-listener/*
     routes:
-    - directResponse:
-        status: 500
-      match:
+    - match:
         prefix: /
       name: direct-route
+      route:
+        cluster: direct-route-dest
+        upgradeConfigs:
+        - upgradeType: websocket