Envoy+gRPC跨域报错:x-user-agent不在Access-Control-Allow-Headers允许列表
Envoy + gRPC 遇到CORS跨域问题
浏览器报错信息
Access to XMLHttpRequest at 'https://example.org:8443/main.MyService/Ping' from origin 'https://example.org' has been blocked by CORS policy: Request header field x-user-agent is not allowed by Access-Control-Allow-Headers in preflight response.
相关截图


Envoy配置文件
# Admin settings admin: access_log_path: /tmp/admin_access.log address: socket_address: address: 0.0.0.0 port_value: 9901 # Static resource configurations static_resources: listeners: - name: listener_0 address: socket_address: address: 0.0.0.0 port_value: 8443 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 codec_type: auto stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] cors: allow_origin_string_match: - safe_regex: google_re2: {} regex: '^https?://example.org:[0-9]{4,5}$' allow_headers: "authorization, keep-alive, user-agent, cache-control, content-type, content-transfer-encoding, custom-header-1, x-accept-content-transfer-encoding, x-accept-response-streaming, x-grpc-web, x-user-agent, grpc-timeout" allow_methods: "GET, POST, OPTIONS" max_age: "1d" routes: - match: prefix: "/" headers: - name: ":method" exact_match: "OPTIONS" direct_response: status: 200 - match: prefix: "/auth/google/callback" route: cluster: sample_cluster timeout: seconds: 60 - match: prefix: "/" route: cluster: sample_cluster timeout: seconds: 60 request_headers_to_remove: ["x-user-agent"] response_headers_to_remove: ["x-user-agent"] response_headers_to_add: - header: key: "Access-Control-Allow-Origin" value: "https://example.org" access_log: - name: envoy.access_loggers.stdout typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog # HTTP filter settings http_filters: # gRPC-Web filter - name: envoy.filters.http.grpc_web typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb # CORS filter - name: envoy.filters.http.cors typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors # HTTP router filter - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router transport_socket: # Corrected indentation level name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext common_tls_context: tls_certificates: - certificate_chain: {filename: "/etc/envoy/origin-public.pem"} private_key: {filename: "/etc/envoy/origin-private.pem"} # Cluster settings clusters: - name: sample_cluster connect_timeout: 0.25s type: logical_dns http2_protocol_options: {} load_assignment: cluster_name: sample_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: backend # Change to your gRPC server address port_value: 50051 # Change to your gRPC server port
问题排查与修复
核心问题点
- OPTIONS请求被直接拦截返回:你配置了对所有OPTIONS请求直接返回200的路由规则,导致Envoy的CORS过滤器完全没机会处理预请求,自然不会返回浏览器需要的
Access-Control-Allow-Headers头。 - CORS规则与手动头冲突:同时在virtual_host的cors配置和
response_headers_to_add里设置跨域Origin头,会导致头信息重复或规则冲突。 - Origin正则不匹配:你配置的
allow_origin_string_match正则要求带端口,但实际请求的origin是https://example.org(无端口),导致规则不生效。 - 请求头移除时机错误:在CORS过滤器处理前就移除
x-user-agent,过滤器无法识别这个头是否需要被允许。
修复步骤
- 删除OPTIONS请求的直接返回路由:让CORS过滤器自动处理预请求,它会根据配置生成正确的响应头。
- 移除手动添加的
Access-Control-Allow-Origin头:依赖virtual_host下的cors配置自动生成,避免冲突。 - 修正Origin匹配正则:调整为
^https?://example.org(:[0-9]{4,5})?$,同时匹配带端口和不带端口的origin。 - 保留
x-user-agent在allow_headers中:确保浏览器预请求时能得到允许该头的响应。
修改后的关键配置片段
route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] cors: allow_origin_string_match: - safe_regex: google_re2: {} regex: '^https?://example.org(:[0-9]{4,5})?$' allow_headers: "authorization, keep-alive, user-agent, cache-control, content-type, content-transfer-encoding, custom-header-1, x-accept-content-transfer-encoding, x-accept-response-streaming, x-grpc-web, x-user-agent, grpc-timeout" allow_methods: "GET, POST, OPTIONS" max_age: "1d" routes: - match: prefix: "/auth/google/callback" route: cluster: sample_cluster timeout: seconds: 60 - match: prefix: "/" route: cluster: sample_cluster timeout: seconds: 60 request_headers_to_remove: ["x-user-agent"] response_headers_to_remove: ["x-user-agent"] # 移除手动添加的Access-Control-Allow-Origin配置
内容的提问来源于stack exchange,提问作者Jill Clover
相关产品推荐
相关产品推荐

