Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first draw of making DSG work with browser #230

Merged
merged 1 commit into from
Nov 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 56 additions & 4 deletions docs/how-to/web.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,60 @@ Web
Description
-----------

Usage
-----
It's possible to use gRPC in a broswer considering some limitations (See `state-of-grpc-web <https://grpc.io/blog/state-of-grpc-web/>`_.
Using it allow you to have only one interface for all your customer. It also enable server side streams that is not existing in classic REST protocols.

Example
-------
All the next step described here can be found in the `dsg-example repository <https://github.com/socotecio/django-socio-grpc-example>`_ in the `frontend/grpc-web-example <https://github.com/socotecio/django-socio-grpc-example/frontend/grpc-web-example>` directory.

We will use `BUF <https://buf.build/>`_ to generate the JS doc. Note that grpc-web have it's own protoc-gen-grpc-web plugin to generate JS file but it `doesn't generate js ESM module <https://github.com/grpc/grpc-web/tree/master#import-style>`_ and it is `not compatible with Vite easily <https://github.com/grpc/grpc-web/issues/1242>`_.

It work the same as traditionnal gRPC except that a proxy is charged to transform traditional request into enforced HTTP/2 gRPC compatible one.

Depending on the backend you use `you may even not need a proxy but just some middleware<https://github.com/grpc/grpc-web#ecosystem>`_. But in Python it's still needed for now.

If you are considering a production deployement on a kubernetes cluster you may consider the usage of `Istio <https://istio.io/>`_ that produce a `grpc-web proxy out of the box <https://istio.io/latest/docs/ops/configuration/traffic-management/protocol-selection/>`_ without any specific configuration. For local development follow next steps.

The Envoy Proxy & docker image
-----------

The default recommended proxy is `Envoy <https://www.envoyproxy.io/>`_. The doc of `grpc-web <https://github.com/grpc/grpc-web>`_ document how to use it and even give you a example config file: `envoy.yaml <https://github.com/grpc/grpc-web/blob/master/net/grpc/gateway/examples/echo/envoy.yaml>`_

In this example file the importante lines you need to know beacause you may need to change them are:
- l.10: specify the listening port
- l.60 & 61: specify the address and port of the grpc-server
- l.26 & 48: cluster name need to match together

To help you understand how to launch it you can have a look in our example repository:
- `Envoy configuration and dockerfile <https://github.com/socotecio/django-socio-grpc-example/envoy>`_
- `Docker compose conf <https://github.com/socotecio/django-socio-grpc-example/envoy#L33>`_

This can also be launched in production environment but if the envoy proxy is not located in the same local network it can bring latency. Please consider using `Istio <https://istio.io/>`_ if in kubernetes deployement

Generating JS client
-----------

By using BUF you can upload your proto files directly to `BSR <https://buf.build/product/bsr>`_ and use their SDK to `dynamically generate files while pushing to registry <https://buf.build/docs/bsr/generated-sdks/npm>`_.

But to help understand how it work and making simple example we will use `locally generated files <https://connectrpc.com/docs/web/generating-code#local-generation>`_
Here is the step needed:

- Install dependencies (3 in dev mode and 3 in normal mode ). `Example <https://github.com/socotecio/django-socio-grpc-example/frontend/grpc-web-example/package.json>`_
- Create the buf.gen.yaml with at least the es and the connect-es plugin. Even if it can be anywhere we recommend you to put it at the root of your js folder or your API folder. The example will only work if at the root of a vue vite/webpack project as it expect a src folder to exist. `Example <https://github.com/socotecio/django-socio-grpc-example/frontend/grpc-web-example/buf.gen.yaml>`_
- Copy the proto file into a proto directory created in the folder of the buf.gen.yaml file. `Example <https://github.com/socotecio/django-socio-grpc-example/frontend/grpc-web-example/proto>`_
- Launch the command: npx buf generate proto `Explanation <https://github.com/socotecio/django-socio-grpc-example/README.md#how-to-update-the-js-file-when-api-update>`_
- A src/gen folder should create with two file. _connect.js file with the Services/Controllers file and _pb.js with request and response message file `Example <https://github.com/socotecio/django-socio-grpc-example/frontend/grpc-web-example/src/gen>`_

Once this two file are generated you are good to go to the next step


Using JS client
-----------

BUF already documented this part: `Using clients <https://connectrpc.com/docs/web/using-clients>`_.

But there is some details that can be confusing:
- You need to use the `createGrpcWebTransport protocol <https://connectrpc.com/docs/web/choosing-a-protocol>_`.
- If proto was generated by DSG then the _connect.js file export Service name with Controller instead of Service name. In the BUF doc ElizaService should have been ElizaController
- If API field use snake_case they should be setted and getted by camelCase if using the createGrpcWebTransport as grpc-web automatically convert fields.

See `our DSG example for more explicit example <https://github.com/socotecio/django-socio-grpc-example/src/components/APIExample.vue>`_