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

Chrome extension to display decoded grpc messages in the web console

Open mitar opened this issue 5 years ago β€’ 11 comments

I think it would be very useful to be able to debug grpc messages in the web console, in the network tab.

mitar avatar Oct 07 '18 05:10 mitar

It will be ideal if we have something like Swagger for gRPC-Web :) I don't want to decode binary format, but I want to have some tool which let me manually enter data in human format (JSON, YAML or simply filling several textbox) and send this data to server in binary. Also I want get deserialized response from server in this tool. I think tool pregenerate message's format and service methods from proto file.

razonrus avatar Oct 25 '18 05:10 razonrus

It's possible to just use JSON with gRPC. I'm not yet sure how well the various proxies handle it, but I've written about using JSON with a Go gRPC server here: https://jbrandhorst.com/post/grpc-json/. There's a also a slightly more complicated (imo) tutorial on the official grpc blog: https://grpc.io/blog/grpc-with-json.

That said, it would be nice to show an example of a gRPC-Web client using JSON as the payload encoding in an example.

johanbrandhorst avatar Oct 25 '18 06:10 johanbrandhorst

This was a similar issue our Frontend teams where facing, so I put together a simple Chrome extension:

https://github.com/SafetyCulture/grpc-web-devtools/

Right now it is very basic, but has a lot of potential. Not published to the Chrome store at the moment, but should be easy enough to install locally.

As of today, it only supports Unary request via the PromiseClient as that is what we use, but should be easy to enable callback requests and streaming.

Ideally some of this code would better sit within this repo to make intercepting the req/res and sending to the dev tools panel easier (client side interceptors would be another good option).

Keen for people to try this tool out (PRs welcome) and maybe we can merge it back to this project once it becomes a bit more stable.

I'm hoping that our Frontend teams will help me make the UI better, with more features: search, clear, pause etc. Was also thinking that a "mock" response would be a cool feature tool; allowing a Frontend Engineer develop without a backend server and proxy.

rogchap avatar Apr 16 '19 11:04 rogchap

@rogchap Thanks for your work on grpc-web devtoosls. We are happy to host the chrome extension in this repo. @stanley-cheung

JSON support in grpc-web is being considered. OTOH, the protobuf javascript team is actively working on optimizing the efficiency and (generated) code size of the current protobuf JS library.

For ease of debugging, dev tools may prove to be sufficient than adding JSON support for browser clients ... and JSON will add overhead on the server-side and may also require proxy support for some languages.

wenbozhu avatar May 01 '19 21:05 wenbozhu

@wenbozhu Thanks, that’s great.

Just recently published the dev tools to the Chrome Web Store: https://chrome.google.com/webstore/detail/grpc-web-developer-tools/ddamlpimmiapbcopeoifjfmoabdbfbjj

Happy to move the extension to this repo; what do you propose the next steps to be?

Couple of questions:

  • Do we transfer this as one (massive) PR?
  • Are you happy that the Dev tool panel is written in React?

rogchap avatar May 05 '19 12:05 rogchap

Ok... so I've thought more about this (after a nights sleep) and I have an idea on how this could play out:

  1. PR to expose DevTools messages
  2. PR for Implementation of the DevTools UI and Extension

Let me know what you think @wenbozhu @stanley-cheung

1. DevTools messages

The extension today uses a content_script.js to inject some code that the web page (the client implementation) so that we can override the rpcCall and unaryCall calls (not done streaming yet).

This provides the API to expose the grpc client to the Devtools via:

const enableDevTools = window.__GRPCWEB_DEVTOOLS__ || (() => {});
const client = new EchoServiceClient('http://myapi.com');
enableDevTools([
  client,
]);

Although this works, any changes to the rpcCall and unaryCall in gRPC-Web would mean updating in the extension too, which is not ideal. Ideally we would have the Devtools messaging calls within the gRPC-Web javascript package within rpcCall itself; this means that we would not need to do some crazy overriding of the methods.

The main body of this message is this:

window.postMessage({
   type: "__GRPCWEB_DEVTOOLS__",
   method,
  request: request.toObject(),
  response: err ? null : response.toObject(),
  error: err,
}, "*");

By having this code directly within this project would mean the extension would not need to inject any code to the web page, and the developer would not need to pass their gRPC client through an enableDevTools function.

That said, developers will still want to enable/disable DevTools tracking, so I would propose a client option to turn this on/off. eg:

const client = new ExampleClient('http://0.0.0.0:8080', null, { enableDevTools: !!__DEV__ });

With the above step implemented the current chrome extension will work and display the network messages as it does today.

2. DevTools UI Extension

This can now be implemented independently of step 1, as a second (or group) of PRs. The main state management is redux with a react UI, however this is easy to change if we prefer to use another technology. All the extension messaging code can stay the same.

At some point we can then publish the new extension and I can remove/redirect to the "official" version.

rogchap avatar May 06 '19 02:05 rogchap

@rogchap Thanks for the great work here! This is looking exciting.

So looks like there is a bit of gray area / overlap between this and a proper Interceptor API.

In my mind, devtools / browser extension should be transparent to the core library. If we have to update the core library / API, I'd prefer it to be for the purpose of introducing the Interceptor API. So I am a bit reluctant to introduce API to the client constructor you mentioned like this:

const client = new ExampleClient('http://0.0.0.0:8080', null, { enableDevTools: !!__DEV__ });

I think the intention was good, but at the API level it's debatable. I'd like to see other users chime in as well, if any of you from the community has an opinion on this.

I think that, if the extension is transparent to the core library, having the extension tied to the API (meaning that if we update the core API, the extension has to chanage), is OK. So what you proposed here:

const enableDevTools = window.__GRPCWEB_DEVTOOLS__ || (() => {});
const client = new EchoServiceClient('http://myapi.com');
enableDevTools([
  client,
]);

looks OK to me. As in, the above is saying, I am writing some additional code that wraps the existing public gRPC-Web client object, and do some stuff with it for the browser extension UI purposes. For that purposes, yes this gets tied when rpcCall and/or unaryCall signature changed, which itself is an unlikely event.

Again, thank you very much for taking this on. We should keep the dialog open.

stanley-cheung avatar May 07 '19 22:05 stanley-cheung

Funny you should mention interceptors as this was what I looked for when I first started putting this together! I even commented on the issue to see if we could get the proposal aligned: https://github.com/grpc/grpc-web/issues/283#issuecomment-483074550

Happy to keep the current API the same and provide the whole thing in one PR. Do you have any feedback on the UI part (specifically it using React & Redux) @stanley-cheung?

In terms of next steps, I want to get the extension displaying streaming requests/responses and highlight them vs unary calls (currently only unary is supported); I'll do this in my current project. Once this is done I can provide time to port to this project with any changes.

Alternatively I can put this on hold, and provide time to help with the Interceptor work, and come back to this once that is merged. πŸ˜‰

rogchap avatar May 08 '19 06:05 rogchap

Maybe something like Charles Protobuf Text will be OK?

https://www.charlesproxy.com/documentation/using-charles/protocol-buffers/#text_viewer

// No message type specified.
1: 0
3: 0
4: "..."
5 {
  1: 0
  2: "..."
  3: 0
  4 {
    1: 0
    2: "..."
    3 {
      1: "..."
      2: "..."
      3: 1
    }
    4 {
      1: "..."
      2: "..."
      3: 2
    }
    5 {
      1: "..."
      2: "..."
      3: 3
    }
  }
  5: "..."
  11: 0
}

Sunbreak avatar Mar 31 '21 05:03 Sunbreak

Hello everyone πŸ‘‹

I published a chrome extension to debug gRPC-web activity: https://github.com/iendeavor/grpc-devtools

It uses a Network Panel-like UI and is made using the interceptor API.

Hope it helps. πŸ˜ƒ

soc221b avatar Aug 14 '22 06:08 soc221b

@iendeavor Thanks for your contribution! Very cool!πŸ˜ƒ

sampajano avatar Aug 14 '22 16:08 sampajano