[gRPC-JSON transcoder] Request validation triggers 404 for CORS preflight OPTIONS requests
- Dominant language
- C++
- Stars
- 28.9k
- Forks
- 5.6k
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 437
Description
*Title*: Request validation triggers 404 for CORS preflight OPTIONS requests
*Description*:
When a grpc-json transcoder is deployed with CORS enabled preflight (OPTIONS) requests fail if request validation is enabled. This likely happens because the transcoder attempts to validate the HTTP request's method before CORS, triggering an error as OPTIONS is not recognized as a valid "transcodable" method.
---
*Repro steps*:
Setup the grpc-json transcoder with request validation enabled and CORS rules and observe that when `request_validation_options` with `reject_unknown_method` is set CORS will fail with a 404 error:
```yaml
cors:
allow_origin_string_match: [{ prefix: "*" }]
allow_methods: GET, PUT, DELETE, POST, PATCH, OPTIONS
allow_headers: authorization, keep-alive, user-agent, cache-control, content-type, content-transfer-encoding, x-accept-content-transfer-encoding, x-accept-response-streaming, x-user-agent, x-grpc-web, referer
expose_headers: grpc-status, grpc-message, x-envoy-upstream-service-time
allow_credentials: true
routes:
- match: { prefix: "/" }
route: { cluster: grpc, timeout: 60s }
```
```yaml
request_validation_options:
reject_unknown_method: true
reject_unknown_query_parameters: true
```
Comment out or remove the `request_validation_options` block and observe that CORS preflight (OPTIONS) works again correctly:
```yaml
# request_validation_options:
# reject_unknown_method: true
# reject_unknown_query_parameters: true
```
---
*Config*:
```
admin:
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
- name: rest-listener
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: grpc_json
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
cors:
allow_origin_string_match: [{ prefix: "*" }]
allow_methods: GET, PUT, DELETE, POST, PATCH, OPTIONS
allow_headers: authorization, keep-alive, user-agent, cache-control, content-type, content-transfer-encoding, x-accept-content-transfer-encoding, x-accept-response-streaming, x-user-agent, x-grpc-web, referer
expose_headers: grpc-status, grpc-message, x-envoy-upstream-service-time
allow_credentials: true
routes:
- match: { prefix: "/" }
route: { cluster: grpc, timeout: 60s }
http_filters:
- name: envoy.filters.http.cors
- name: envoy.filters.http.grpc_json_transcoder
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder
services:
- animeshon.crossrefs.v1alpha1.Referrer
# - google.iam.v1.IAMPolicy
- google.longrunning.Operations
print_options:
add_whitespace: true
always_print_enums_as_ints: false
always_print_primitive_fields: true
preserve_proto_field_names: false
request_validation_options:
reject_unknown_method: true
reject_unknown_query_parameters: true
convert_grpc_status: true
proto_descriptor: /etc/envoy/proto.bin
- name: envoy.filters.http.router
clusters:
- name: grpc
connect_timeout: 5s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
dns_lookup_family: V4_ONLY
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: grpc
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: host.docker.internal
port_value: 5000
```
Contributor guide
Assessment
This issue has not been assessed yet.