Skip to content

Commit bd2380d

Browse files
authored
fix: support binaryData in direct response (#7036)
* Support binaryData in custom response Signed-off-by: Karol Szwaj <[email protected]>
1 parent c68db79 commit bd2380d

15 files changed

+144
-44
lines changed

internal/gatewayapi/backendtrafficpolicy.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,50 +1138,57 @@ func buildResponseOverride(policy *egv1a1.BackendTrafficPolicy, resources *resou
11381138
}, nil
11391139
}
11401140

1141-
func checkResponseBodySize(b *string) error {
1141+
func checkResponseBodySize(b []byte) error {
11421142
// Make this configurable in the future
11431143
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route.proto.html#max_direct_response_body_size_bytes
11441144
maxDirectResponseSize := 4096
1145-
lenB := len(*b)
1145+
lenB := len(b)
11461146
if lenB > maxDirectResponseSize {
11471147
return fmt.Errorf("response.body size %d greater than the max size %d", lenB, maxDirectResponseSize)
11481148
}
11491149

11501150
return nil
11511151
}
11521152

1153-
func getCustomResponseBody(body *egv1a1.CustomResponseBody, resources *resource.Resources, policyNs string) (*string, error) {
1153+
func getCustomResponseBody(body *egv1a1.CustomResponseBody, resources *resource.Resources, policyNs string) ([]byte, error) {
11541154
if body != nil && body.Type != nil && *body.Type == egv1a1.ResponseValueTypeValueRef {
11551155
cm := resources.GetConfigMap(policyNs, string(body.ValueRef.Name))
11561156
if cm != nil {
11571157
b, dataOk := cm.Data["response.body"]
11581158
switch {
11591159
case dataOk:
1160-
if err := checkResponseBodySize(&b); err != nil {
1160+
body := []byte(b)
1161+
if err := checkResponseBodySize(body); err != nil {
11611162
return nil, err
11621163
}
1163-
return &b, nil
1164+
return body, nil
11641165
case len(cm.Data) > 0: // Fallback to the first key if response.body is not found
11651166
for _, value := range cm.Data {
1166-
b = value
1167-
break
1167+
body := []byte(value)
1168+
if err := checkResponseBodySize(body); err != nil {
1169+
return nil, err
1170+
}
1171+
return body, nil
11681172
}
1169-
if err := checkResponseBodySize(&b); err != nil {
1170-
return nil, err
1173+
case len(cm.BinaryData) > 0:
1174+
for _, binData := range cm.BinaryData {
1175+
if err := checkResponseBodySize(binData); err != nil {
1176+
return nil, err
1177+
}
1178+
return binData, nil
11711179
}
1172-
return &b, nil
11731180
default:
11741181
return nil, fmt.Errorf("can't find the key response.body in the referenced configmap %s", body.ValueRef.Name)
11751182
}
1176-
11771183
} else {
11781184
return nil, fmt.Errorf("can't find the referenced configmap %s", body.ValueRef.Name)
11791185
}
11801186
} else if body != nil && body.Inline != nil {
1181-
if err := checkResponseBodySize(body.Inline); err != nil {
1187+
inlineValue := []byte(*body.Inline)
1188+
if err := checkResponseBodySize(inlineValue); err != nil {
11821189
return nil, err
11831190
}
1184-
return body.Inline, nil
1191+
return inlineValue, nil
11851192
}
11861193

11871194
return nil, nil

internal/gatewayapi/testdata/backendtrafficpolicy-with-response-override.out.yaml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ xdsIR:
524524
name: X-Set-Header
525525
value:
526526
- set-404
527-
body: gateway-1 Not Found
527+
body: Z2F0ZXdheS0xIE5vdCBGb3VuZA==
528528
contentType: text/plain
529529
- match:
530530
statusCodes:
@@ -534,10 +534,7 @@ xdsIR:
534534
start: 501
535535
name: backendtrafficpolicy/default/policy-for-gateway/responseoverride/rule/1
536536
response:
537-
body: |
538-
{
539-
"error": "Internal Server Error"
540-
}
537+
body: ewogICJlcnJvciI6ICJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3IiCn0K
541538
contentType: application/json
542539
readyListener:
543540
address: 0.0.0.0
@@ -622,7 +619,7 @@ xdsIR:
622619
- value: 404
623620
name: backendtrafficpolicy/default/policy-for-route-1/responseoverride/rule/0
624621
response:
625-
body: httproute-1 Not Found
622+
body: aHR0cHJvdXRlLTEgTm90IEZvdW5k
626623
contentType: text/plain
627624
- match:
628625
statusCodes:
@@ -632,10 +629,7 @@ xdsIR:
632629
start: 501
633630
name: backendtrafficpolicy/default/policy-for-route-1/responseoverride/rule/1
634631
response:
635-
body: |
636-
{
637-
"error": "Internal Server Error"
638-
}
632+
body: ewogICJlcnJvciI6ICJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3IiCn0K
639633
contentType: application/json
640634
- destination:
641635
metadata:

internal/gatewayapi/testdata/httproute-with-direct-response.in.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,27 @@ httpRoutes:
8888
group: gateway.envoyproxy.io
8989
kind: HTTPRouteFilter
9090
name: direct-response-too-long
91+
- apiVersion: gateway.networking.k8s.io/v1
92+
kind: HTTPRoute
93+
metadata:
94+
name: direct-response-binary
95+
namespace: default
96+
spec:
97+
parentRefs:
98+
- name: gateway-1
99+
namespace: envoy-gateway
100+
sectionName: http
101+
rules:
102+
- matches:
103+
- path:
104+
type: PathPrefix
105+
value: /logo
106+
filters:
107+
- type: ExtensionRef
108+
extensionRef:
109+
group: gateway.envoyproxy.io
110+
kind: HTTPRouteFilter
111+
name: direct-response-binary-logo
91112
configMaps:
92113
- apiVersion: v1
93114
kind: ConfigMap
@@ -96,6 +117,13 @@ configMaps:
96117
namespace: default
97118
data:
98119
response.body: '{"error": "Internal Server Error"}'
120+
- apiVersion: v1
121+
kind: ConfigMap
122+
metadata:
123+
name: logo-binary-data
124+
namespace: default
125+
binaryData:
126+
logo.png: iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==
99127
httpFilters:
100128
- apiVersion: gateway.envoyproxy.io/v1alpha1
101129
kind: HTTPRouteFilter
@@ -156,3 +184,18 @@ httpFilters:
156184
body:
157185
type: Inline
158186
inline: "-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
187+
- apiVersion: gateway.envoyproxy.io/v1alpha1
188+
kind: HTTPRouteFilter
189+
metadata:
190+
name: direct-response-binary-logo
191+
namespace: default
192+
spec:
193+
directResponse:
194+
contentType: image/png
195+
statusCode: 502
196+
body:
197+
type: ValueRef
198+
valueRef:
199+
group: ""
200+
kind: ConfigMap
201+
name: logo-binary-data

internal/gatewayapi/testdata/httproute-with-direct-response.out.yaml

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ gateways:
1616
protocol: HTTP
1717
status:
1818
listeners:
19-
- attachedRoutes: 3
19+
- attachedRoutes: 4
2020
conditions:
2121
- lastTransitionTime: null
2222
message: Sending translated listener configuration to the data plane
@@ -168,6 +168,45 @@ httpRoutes:
168168
name: gateway-1
169169
namespace: envoy-gateway
170170
sectionName: http
171+
- apiVersion: gateway.networking.k8s.io/v1
172+
kind: HTTPRoute
173+
metadata:
174+
name: direct-response-binary
175+
namespace: default
176+
spec:
177+
parentRefs:
178+
- name: gateway-1
179+
namespace: envoy-gateway
180+
sectionName: http
181+
rules:
182+
- filters:
183+
- extensionRef:
184+
group: gateway.envoyproxy.io
185+
kind: HTTPRouteFilter
186+
name: direct-response-binary-logo
187+
type: ExtensionRef
188+
matches:
189+
- path:
190+
type: PathPrefix
191+
value: /logo
192+
status:
193+
parents:
194+
- conditions:
195+
- lastTransitionTime: null
196+
message: Route is accepted
197+
reason: Accepted
198+
status: "True"
199+
type: Accepted
200+
- lastTransitionTime: null
201+
message: Resolved all the Object references for the Route
202+
reason: ResolvedRefs
203+
status: "True"
204+
type: ResolvedRefs
205+
controllerName: gateway.envoyproxy.io/gatewayclass-controller
206+
parentRef:
207+
name: gateway-1
208+
namespace: envoy-gateway
209+
sectionName: http
171210
infraIR:
172211
envoy-gateway/gateway-1:
173212
proxy:
@@ -243,7 +282,7 @@ xdsIR:
243282
value:
244283
- set-502
245284
directResponse:
246-
body: '{"error": "Internal Server Error"}'
285+
body: eyJlcnJvciI6ICJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3IifQ==
247286
statusCode: 502
248287
hostname: '*.envoyproxy.io'
249288
isHTTP2: false
@@ -262,7 +301,7 @@ xdsIR:
262301
value:
263302
- text/plain
264303
directResponse:
265-
body: OK
304+
body: T0s=
266305
statusCode: 200
267306
hostname: '*.envoyproxy.io'
268307
isHTTP2: false
@@ -275,6 +314,25 @@ xdsIR:
275314
distinct: false
276315
name: ""
277316
prefix: /inline
317+
- addResponseHeaders:
318+
- append: false
319+
name: Content-Type
320+
value:
321+
- image/png
322+
directResponse:
323+
body: iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==
324+
statusCode: 502
325+
hostname: '*.envoyproxy.io'
326+
isHTTP2: false
327+
metadata:
328+
kind: HTTPRoute
329+
name: direct-response-binary
330+
namespace: default
331+
name: httproute/default/direct-response-binary/rule/0/match/0/*_envoyproxy_io
332+
pathMatch:
333+
distinct: false
334+
name: ""
335+
prefix: /logo
278336
readyListener:
279337
address: 0.0.0.0
280338
ipFamily: IPv4

internal/ir/xds.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ type CustomResponse struct {
625625
ContentType *string `json:"contentType,omitempty"`
626626

627627
// Body of the Custom Response
628-
Body *string `json:"body,omitempty"`
628+
Body []byte `json:"body,omitempty"`
629629

630630
// StatusCode will be used for the response's status code.
631631
StatusCode *uint32 `json:"statusCode,omitempty"`

internal/ir/zz_generated.deepcopy.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/xds/translator/custom_response.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,10 @@ func (c *customResponse) buildRedirectAction(r ir.ResponseOverrideRule) (*anypb.
422422
func (c *customResponse) buildResponseAction(r ir.ResponseOverrideRule) (*anypb.Any, error) {
423423
response := &policyv3.LocalResponsePolicy{}
424424

425-
if r.Response.Body != nil && *r.Response.Body != "" {
425+
if len(r.Response.Body) > 0 {
426426
response.BodyFormat = &corev3.SubstitutionFormatString{
427427
Format: &corev3.SubstitutionFormatString_TextFormat{
428-
TextFormat: *r.Response.Body,
428+
TextFormat: string(r.Response.Body),
429429
},
430430
}
431431
}

internal/xds/translator/route.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,10 +524,10 @@ func buildXdsDirectResponseAction(res *ir.CustomResponse) *routev3.DirectRespons
524524
routeAction.Status = *res.StatusCode
525525
}
526526

527-
if res.Body != nil && *res.Body != "" {
527+
if len(res.Body) > 0 {
528528
routeAction.Body = &corev3.DataSource{
529-
Specifier: &corev3.DataSource_InlineString{
530-
InlineString: *res.Body,
529+
Specifier: &corev3.DataSource_InlineBytes{
530+
InlineBytes: res.Body,
531531
},
532532
}
533533
}

internal/xds/translator/testdata/in/xds-ir/accesslog-invalid.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ http:
4444
port: 50000
4545
name: "direct-route-dest/backend/0"
4646
directResponse:
47-
body: "Unknown custom filter type: UnsupportedType"
47+
body: VW5rbm93biBjdXN0b20gZmlsdGVyIHR5cGU6IFVuc3VwcG9ydGVkVHlwZQ==
4848
statusCode: 500

internal/xds/translator/testdata/in/xds-ir/custom-response.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ http:
4949
name: X-Set-Header
5050
value:
5151
- set-404
52-
body: gateway-1 Not Found
52+
body: Z2F0ZXdheS0xIE5vdCBGb3VuZA==
5353
contentType: text/plain
5454
- match:
5555
statusCodes:
@@ -59,10 +59,7 @@ http:
5959
start: 501
6060
name: backendtrafficpolicy/default/policy-for-gateway/responseoverride/rule/1
6161
response:
62-
body: |
63-
{
64-
"error": "Internal Server Error"
65-
}
62+
body: ewogICJlcnJvciI6ICJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3IiCn0K
6663
contentType: application/json
6764
- match:
6865
statusCodes:

0 commit comments

Comments
 (0)