1

I'm new to grpc_web and envoy.

Please help me to setup following things,

  1. GRPC_Go server is running on ec2 instance as a docker container
  2. Dart web client is running on local pc
  3. Need to make grpc call request from dart web app to grpc_go server
  4. Used envoy proxy for the request forward. Envoy proxy is running as a container in same ec2 instance

I'm getting the following error "Response: null, trailers: {access-control-allow-credentials: true, access-control-allow-origin: http://127.0.0.1:9000, vary: Origin})".

Grpc_Go:

package main

import (
"context"
"flag"
"fmt"
"log"
"net"

"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

var (
  port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
   pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
   log.Printf("Received: %v", in.GetName())
   return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, 
error) 
{
   return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}

func main() {
flag.Parse()
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
    log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
    log.Fatalf("failed to serve: %v", err)
 }
} 

GRPC_dart_client:


import 'package:grpc/grpc_web.dart';
import 'package:grpc_web/app.dart';
import 'package:grpc_web/src/generated/echo.pbgrpc.dart';

void main() {
  final channel = GrpcWebClientChannel.xhr(Uri.parse('http://ec2-ip:8080'));
  final service = EchoServiceClient(channel);
  final app = EchoApp(service);

  final button = querySelector('#send') as ButtonElement;
  button.onClick.listen((e) async {
    final msg = querySelector('#msg') as TextInputElement;
    final value = msg.value!.trim();
    msg.value = '';

    if (value.isEmpty) return;

    if (value.indexOf(' ') > 0) {
      final countStr = value.substring(0, value.indexOf(' '));
      final count = int.tryParse(countStr);

      if (count != null) {
        app.repeatEcho(value.substring(value.indexOf(' ') + 1), count);
      } else {
        app.echo(value);
      }
    } else {
      app.echo(value);
    }
  });
}

envoy.yaml:

  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: 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
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: echo_service
                  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,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
          - name: envoy.filters.http.cors
          - name: envoy.filters.http.router
  clusters:
  - name: echo_service
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    load_assignment:
      cluster_name: cluster_0
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: app
                    port_value: 50051

Grpc_go_docker_file:


# Install git.
# Git is required for fetching the dependencies.
RUN apk update && apk add --no-cache git
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Start a new stage from scratch
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the Pre-built binary file from the previous stage. Observe we also copied the .env file
COPY --from=builder /app/main .
# Expose port 50051 to the outside world
EXPOSE 50051

CMD ["./main"] 

Envoy_Docker:


COPY envoy.yaml /etc/envoy/envoy.yaml

CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml -l trace --log-path /tmp/envoy_info.log

I'm stuck with it more than two days, please help me. Thanks in advance

Dinesh
  • 11
  • 2
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Mar 01 '22 at 17:14
  • What are you seeing in the envoy logs? Your question has a lot of moving parts and the issue could well be in the bits you have not shown us (e.g. how the docker containers are being run, network setup etc). Perhaps try to narrow down the issue by using something like [bloomrpc](https://github.com/bloomrpc/bloomrpc)/[Kreya](https://kreya.app/) to test this locally (running docker desktop or similar); confirm the Go App works with gRPC then then introduce envoy/grpcWeb into the mix. – Brits Mar 01 '22 at 20:42

1 Answers1

0

Thank you all, for your reply.

I fixed this issue with IP of the ec2 instance.

clusters:
  - name: echo_service
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    load_assignment:
      cluster_name: cluster_0
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: app
                    port_value: 50051

Instead of container 'address: app' (app is container name) in the envoy.yaml, I used the ip of ec2 instance and container port now envoy is forwarding the request to server.

Brits
  • 14,829
  • 2
  • 18
  • 31
Dinesh
  • 11
  • 2
  • Note that when using docker you don't need to go via the host (and only the `envoy` container needs to be exposed on the host). Changing the `app` in `address: app` to the container name would probably do the job - see [docker networking])(https://docs.docker.com/network/) for info. – Brits Mar 03 '22 at 04:34