I have a remote envoy proxy deployed in AWS with Elastic Beanstalk (for testing) with the configuration below:
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
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: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: grpc_cluster
timeout: 0s
max_stream_duration:
grpc_timeout_header_max: 0s
cors:
allow_origin_string_match:
- prefix: "*"
allow_methods: GET, PUT, DELETE, POST, OPTIONS
allow_headers: keep-alive,accept,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
max_age: "1728000"
expose_headers: custom-header-1,grpc-status,grpc-message
http_filters:
- name: envoy.filters.http.grpc_web
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
- name: envoy.filters.http.cors
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: grpc_cluster
connect_timeout: 0.25s
type: logical_dns
http2_protocol_options: {}
lb_policy: round_robin
load_assignment:
cluster_name: grpc_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: ${server_url}
port_value: ${server_port}
When I test connection to it using grpcurl or even a simple client via nodejs:
import { LightStreamerClient } from "../protos-dist/LightstreamerServiceClientPb";
import { Empty, ServerInfo } from "../protos-dist/lightstreamer_pb";
import { RpcError } from "grpc-web";
const XMLHttpRequest = require("xhr2");
const client = new LightStreamerClient("http://mytest.us-west-1.elasticbeanstalk.com");
globalThis.XMLHttpRequest = XMLHttpRequest;
function getServerInfo(): Promise<[RpcError, ServerInfo]> {
return new Promise((res) => {
client.getServerInfo(new Empty(), null, (_err, response) => {
res([_err, response]);
});
});
}
async function main() {
console.log("Testing envoy server...");
const [err, response] = await getServerInfo();
console.log({ err, response });
console.log("Done.");
}
main();
it returns data as expected.
When I try to run this same grpc-web call from inside a simulated react native ios app, the call to the server fails with error:
[RpcError: Http response at 400 or 500 level, http status code: 0]
Interestingly, when I run the same envoy proxy locally it works fine with all testing mechanisms. Wondering if it has something to do with CORS?
We determined that iOS was blocking the insecure traffic on http, so we made a temporary exception in the Info.plist of our react native app and allowed insecure to our envoy.