grpc-web icon indicating copy to clipboard operation
grpc-web copied to clipboard

Path prefixes: how?

Open smnbbrv opened this issue 4 years ago • 5 comments

Hi all,

I have a very basic question and cannot find an answer yet.

This is what I have from docs:

const echoService = new EchoServiceClient('http://localhost:8080', null, null);

That's all fine until it comes to deployment to the real world where I have just one domain (let's say this is a limitation) and want to split the traffic by path prefixes as one normally does in REST.

In other words this is the desired URL structure:

  • web app: https://example.com
  • grpc-web proxy: https://example.com/grpc-proxy

and the configuration of the client would be

const echoService = new EchoServiceClient('https://example.com/grpc-proxy', null, null);

or even more preferrable

const echoService = new EchoServiceClient('/grpc-proxy', null, null);

There is an option to configure some sort of path prefix strip and make one more proxy step on the envoy itself, so it looks something like

browser => envoy proxy strip path prefix => envoy grpc web proxy => grpc server

However, it looks dirty.

And I am still unsure whether the grpc-web library itself is going to support the non-root path prefixes such as described above in the long run .

Is this possible? Is there an example how to configure envoy in this case?

Thanks in advance.

smnbbrv avatar Jan 09 '20 16:01 smnbbrv

@smnbbrv did you find a solution for this?

nodeworks avatar Feb 18 '20 04:02 nodeworks

Hi @nodeworks

  • the possible way how to do it - yes. Use any reverse proxy that strips the chosen path and handles SSL termination in front of envoy. I used http-proxy-middleware (webpack's standard one) and locally it worked pretty well => should work with any sort of reverse proxy then
  • the answer to my question - no. But this you can see by the thread's activity :)
  • the solution - yes and not really. Although the approach with reverse proxy works well it's not guaranteed that the server streaming (and the whole grpc-web protocol actually) is not going to switch to WebSockets. Proxying them is already harder. So, I did not yet decide whether it is a good solution for me

smnbbrv avatar Feb 18 '20 05:02 smnbbrv

@smnbbrv ah yes, I can confirm this process works with traefik as well. Thanks for the quick response!! Cheers!

nodeworks avatar Feb 18 '20 05:02 nodeworks

Actually finally I got the proper way to handle this. It has a limitation that you need to own the proto files and services to be able to modify them (if they do not supply what's described below).

Every RPC call has the following structure:

/package.subpackage.ServiceName/RpcName

So, it is just enough to give the packages a unique enough name that could be used as a prefix path.

E.g. there is the following service

syntax = "proto3";

import "google/protobuf/empty.proto";

service EchoService {
  rpc Echo(google.protobuf.Empty) returns (google.protobuf.Empty);
}

The Echo call will have the /EchoService/Echo URL path.

Now let's add the proper package.

syntax = "proto3";

// the package name is just an example
package mybackends.echobackend.echo

import "google/protobuf/empty.proto"; 

service EchoService {
  rpc Echo(google.protobuf.Empty) returns (google.protobuf.Empty);
}

and the URL path will become /mybackends.echobackend.echo.EchoService/Echo.

The generated URL is very descriptive and can easily be used to split the calls. These are example masks to match it:

  • /mybackends.* - wraps all backends into one sub-url. Very useful for frontend if you have multiple backends, otherwise you need to keep in mind multiple paths which you are not allowed to use in the frontend routers / page urls. Also could be used by load balancer to delegate path matching to e.g. envoy
  • /mybackends.echobackend.* - points to the specific backend. This one is the load balancer marker to point to the specific backend
  • by going deeper you can further configure atomic services and even calls

@stanley-cheung could this be added to the documentation? I know, probably this repo should not document the sysadmin guides; however the infrastructure is very important here and it's not that easy to find out how to properly configure it...

smnbbrv avatar Feb 19 '20 09:02 smnbbrv

I was up against this same problem. For me, in the end it was a relatively easy fix with the envoy config. Specifically the prefix_rewrite as seen here: image

snarlysodboxer avatar Jun 09 '22 22:06 snarlysodboxer