Ashish Kumar
Ashish Kumar

Reputation: 9

"upstream connect error or disconnect/reset before headers. reset reason: connection failure" after i run envoy proxy

i was making a mern - grpc search app and i wrote envoy.yaml. it's running on docker container successfully but it is showing upstream error on localhost

upstream connect error or disconnect/reset before headers. reset reason: connection failure

this is my envoy.yaml

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: 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: question_service
                            max_grpc_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: question_service
      connect_timeout: 0.25s
      type: LOGICAL_DNS
      http2_protocol_options: {}
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: question_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: host.docker.internal # Change to localhost if not using Docker
                      port_value: 9090
 

this is my server -> server.js

const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");

const { MongoClient } = require("mongodb");

const PROTO_PATH = "./question.proto";
const SERVER_URI = "0.0.0.0:9090";
const MONGO_URI = "mongodb://localhost:27017";
const DB_NAME = "questionsDB";

let db;

const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
const client = new protoDescriptor.question.QuestionService(
  "host.docker.internal:9090", // or "host.docker.internal:9090" for Docker
  grpc.credentials.createInsecure()
);
// Connect to MongoDB
MongoClient.connect(MONGO_URI, { useUnifiedTopology: true })
  .then(async (client) => {
    db = client.db(DB_NAME);
    console.log("Connected to MongoDB");

    // Ensure the collection exists by inserting a dummy document
    const questionsCollection = db.collection("questions");
    const existingDocs = await questionsCollection.countDocuments();
    if (existingDocs === 0) {
      await questionsCollection.insertOne({
        title: "Sample Question",
        questionType: "multiple-choice",
      });
      console.log("Dummy document inserted to initialize database.");
    }
  })
  .catch((err) => {
    console.error("Error connecting to MongoDB:", err);
  });

// gRPC handlers
const searchQuestions = async (call, callback) => {
  try {
    const { query, page, pageSize } = call.request;
    const questionsCollection = db.collection("questions");

    const currentPage = page || 1;
    const limit = pageSize || 10;
    const skip = (currentPage - 1) * limit;

    const queryRegex = new RegExp(query, "i");
    const questions = await questionsCollection
      .find({ title: { $regex: queryRegex } })
      .skip(skip)
      .limit(limit)
      .toArray();

    const totalResults = await questionsCollection.countDocuments({
      title: { $regex: queryRegex },
    });

    const totalPages = Math.ceil(totalResults / limit);

    callback(null, {
      questions: questions.map((q) => ({
        id: q._id.toString(),
        title: q.title,
        questionType: q.questionType,
      })),
      totalResults,
      currentPage,
      totalPages,
    });
  } catch (error) {
    console.error("Error in searchQuestions:", error);
    callback(error);
  }
};

// Create and start the server
const server = new grpc.Server();

server.addService(protoDescriptor.question.QuestionService.service, {
  SearchQuestions: searchQuestions,
});

server.bindAsync(SERVER_URI, grpc.ServerCredentials.createInsecure(), (err, port) => {
  if (err) {
    console.error("Server binding error:", err);
    return;
  }
  console.log(`Server is running on ${SERVER_URI}`);
  server.start();
});

my question.proto

syntax = "proto3";

package question;

service QuestionService {
  rpc SearchQuestions (SearchRequest) returns (SearchResponse);
}

message SearchRequest {
  string query = 1;
  int32 page = 2;
  int32 pageSize = 3;
}

message SearchResponse {
  repeated Question questions = 1;
  int32 totalResults = 2;
  int32 currentPage = 3;
  int32 totalPages = 4;
}

message Question {
  string id = 1;
  string title = 2;
  string questionType = 3;
}

why its happening like this? i have tried every possible means.

i am expecting a mern app working with grpc

Upvotes: 0

Views: 25

Answers (0)

Related Questions