0

I'm currently working on a project where I have a C++ gRPC server and a ReactJS client. The problem is I can't get the client to communicate with the server due to CORS restritions. Everytime I try to call my server from my client (in firefox) I get this error: Http response at 400 or 500 level, http status code: 0, with this reason: Reason: CORS header 'Access-Control-Allow-Origin' missing MDN docs

So far, I have a simple proto file (same on both sides) with one service being the greeter service:

pricing.proto:

syntax = "proto3";

// The greeter service definition.
service GrpcPricer {
// Sends a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
    string name = 1;
}

// The response message containing the greetings
message HelloReply {
    string message = 1;
}

I have my c++ server running locally:

#include <iostream>
#include <string>
#include <fstream>

#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>

#include "pricing.grpc.pb.h"
#include "pricing.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;

class GrpcPricerServiceImpl final : public GrpcPricer::Service
{
public:
    Status SayHello(ServerContext *context, const HelloRequest *request,
                    HelloReply *reply) override
    {
        context->AddInitialMetadata("access-control-allow-origin", "*"); // <- I added this line to try to resolve the CORS restriction error
        std::cout << "Hello " << request->name() << std::endl;
        std::string prefix("Hello ");
        reply->set_message(prefix + request->name());
        return Status::OK;
    }
};

void RunServer()
{
    std::string server_address("0.0.0.0:50051");

    GrpcPricerServiceImpl service;
    grpc::EnableDefaultHealthCheckService(true);
    grpc::reflection::InitProtoReflectionServerBuilderPlugin();
    ServerBuilder builder;
    // Listen on the given address without any authentication mechanism.
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    // Register "service" as the instance through which we'll communicate with
    // clients. In this case it corresponds to a *synchronous* service.
    builder.RegisterService(&service);
    // Finally assemble the server.
    std::unique_ptr<Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << server_address << std::endl;

    // Wait for the server to shutdown. Note that some other thread must be
    // responsible for shutting down the server for this call to ever return.
    server->Wait();
}

int main(int argc, char **argv)
{
    RunServer();
    return 0;
}

And my ReactJS client with a simple call to the greeter service on a button click:

const { HelloRequest, HelloReply } = require('../pricing_pb.js');
  const { GrpcPricerClient } = require('../pricing_grpc_web_pb.js');
    const client = new GrpcPricerClient('http://localhost:50051');
    const request = new HelloRequest();

// This is the function being called 
const callGrpcService = () => {
        client.sayHello(request, {}, (err, response) => {
            if (err) {
                console.error(err.message);
            } else {
                console.log(response.getMessage());
            }
        });

What I've tried is to see if my server was responding and so I use this tool grpcurl. When I use this tool, I can get an answer from the server. Here's the command:

grpcurl -d '{"name": "World"}' -plaintext localhost:50051 GrpcPricer/SayHello

Which gives me the following response:

{
  "message": "Hello World"
}

So I reckon the problem comes from the client side. So I also tried to add some headers/metadata to my request with no success. I also tried the firefox add-on CORS everywhere to get rid of the error but it's not a viable solution and does not seem to work great.

Any Ideas welcomed, thanks

lafak
  • 21
  • 1
  • 6
  • I did not find my error on the client side nor on the server side, so I found a workaround. I used a Flask python server in between the ReactJS client and the C++ server. The flask server receives calls from the client and then calls the c++ server and sends back the response to the client. It seems like an extra-layer but it works fine for my project since the flask server also makes calculation with python – lafak Mar 20 '23 at 15:44

0 Answers0