I'm attempting to send data to http://localhost:50051/helloworld.Greeter/SayHello
, but I'm encountering the following error in the browser console:
POST http://localhost:50051/helloworld.Greeter/SayHello net::ERR_INVALID_HTTP_RESPONSE
....
(index):49 Error: TypeError: Failed to fetch
There are no errors shown in the server console.
server.mjs
):import grpc from "@grpc/grpc-js";
import protoLoader from "@grpc/proto-loader";
import path from "path";
import { fileURLToPath } from "url";
const PROTO_PATH = path.join(process.cwd(), "./helloworld.proto");
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {});
const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;
function sayHello(call, callback) {
callback(null, { message: "Hello " + call.request.name });
}
function main() {
const server = new grpc.Server();
server.addService(helloProto.Greeter.service, { sayHello: sayHello });
server.bindAsync(
"0.0.0.0:50051",
grpc.ServerCredentials.createInsecure(),
() => {
server.start();
console.log("Server running at http://0.0.0.0:50051");
}
);
}
main();
I run the server using node server.mjs
.
index.html
):<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gRPC Client</title>
<script src="https://cdn.jsdelivr.net/npm/protobufjs/dist/protobuf.min.js"></script>
</head>
<body>
<script>
// Load the protobuf definitions
const protoPath = "helloworld.proto";
protobuf.load(protoPath, (err, root) => {
if (err) throw err;
const HelloRequest = root.lookupType("helloworld.HelloRequest");
const HelloReply = root.lookupType("helloworld.HelloReply");
console.log({ f: HelloRequest });
// Create a HelloRequest message
const payload = { name: "World" };
const errMsg = HelloRequest.verify(payload);
if (errMsg) throw Error(errMsg);
const message = HelloRequest.create(payload);
const buffer = HelloRequest.encode(message).finish();
console.log({ buffer });
// Send the request using fetch
fetch("http://localhost:50051/helloworld.Greeter/SayHello", {
method: "POST",
headers: {
"Content-Type": "application/x-protobuf",
},
body: buffer,
})
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.arrayBuffer();
})
.then((responseBuffer) => {
const replyMessage = HelloReply.decode(
new Uint8Array(responseBuffer)
);
console.log(`Greeting: ${replyMessage.message}`);
})
.catch((error) => {
console.error("Error:", error);
});
});
</script>
</body>
</html>
I run the client using npx http-server -o
.
helloworld.proto
):syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
"dependencies": {
"@grpc/grpc-js": "^1.11.1",
"@grpc/proto-loader": "^0.7.13",
"cors": "^2.8.5",
"express": "^4.19.2"
}
I'm not seeing any errors on the server side. What could be causing this issue, and how can I resolve it?
You cannot use a browser as a gRPC client because browsers don't support HTTP/2 and this prorocol is required by gRPC.
You can use a technology such as gRPC-Web to provide a proxy for your web client.