Skip to content

GRPC Web Proxy to enable Browser Integration and Eliminate Electron IPC #235

@CMCDragonkai

Description

@CMCDragonkai

Specification

We can separate the networking to 3 layers:

  • P2P application layer - e.g. kademlia, automerge, nodes domain
  • RPC layer - e.g. grpc (and once considered jsonrpc but it's too late now)
  • Data Transfer layer - UTP, Wireguard, QUIC

The RPC layer is what enables us to have rich communication protocols for:

  • Unary
  • Client Streaming, Server Streaming and Duplex Streaming

At the moment we have incorporated GRPC into js-polykey with the usage of these libraries:

    "@grpc/grpc-js": "^1.2.5",
    "google-protobuf": "^3.14.0",
    "@types/google-protobuf": "^3.7.4",
    "grpc_tools_node_protoc_ts": "^5.1.3",

This is working great for Agent to Agent and Client to Agent communication. However there are some challenges:

  • Browsers do not currently have a way of calling the GRPC protocol at all - this means browser extensions cannot make use of the same API that we use in our client service
  • PK GUI which is built on electron uses Electron IPC in the main Node process as a bridge between the renderer Vue application that runs in Chrome and the PK Agent. This adds an extra level of indirection (increasing latency) and work that should not have been needed.

There is a solution called GRPC-web. It's discussed here: https://grpc.io/blog/state-of-grpc-web/

image

The basic idea is to use a separate client library for the browser that uses browser-native protocols to perform GRPC operations.

There are some challenges here:

  • The GRPC protocol is limited when used with grpc-web. The 2 implementations of it appears to lack both client streaming and duplex streaming. That means only unary and server streaming calls are available. This is not a huge issue since I don't think we have any calls on the client service that needs to use client streaming nor duplex streaming.
  • The GRPC-Web does require a separate client library and thus separately generated stubs. The https://github.com/improbable-eng/grpc-web and https://github.com/grpc/grpc-web#client-configuration-options show how you need to generate additional marshaling code. Note that the official grpc/grpc-web implementation is the closest to how we already generate marshaling code in scripts/proto-generate.sh, it's just an additional output.
  • GRPC-Web also requires a "proxy" that proxies GRPC-Web to normal GRPC. There are several in-process proxy implementations in Java and Golang. However none for Nodejs. It is ideal, somewhat necessary that we have an in-process proxy to avoid having to run separate process. We can take a look at existing implementations to see how we would implement our own in-process proxy.

Having GRPC-Web supported and an in-process proxy would mean:

Additional context

Note that there are multiple transports available in the libraries: https://github.com/improbable-eng/grpc-web/blob/master/client/grpc-web/docs/transport.md#built-in-transports. It seems to claim that websocket based transports actually enable both client and duplex streaming, so I'm guessing there's no need to ever go down the route of HTTP2 based transports and just focus on web socket transports?

At any case, for our usecase as we expect a limited deployment environment (browser extensions on latest browsers), it's fine to support only 1 transport.

Tasks

  1. ...
  2. ...
  3. ...

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions