Reputation: 9
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