Skip to content

Commit

Permalink
IRES-508: Fix streaming interceptor (#170)
Browse files Browse the repository at this point in the history
* IRES-508: Fix streaming interceptor

* update version
  • Loading branch information
matt-lewandowski authored Nov 6, 2023
1 parent 7b97172 commit 3faf870
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 53 deletions.
114 changes: 62 additions & 52 deletions public/connect-web-interceptor.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,67 @@
// This interceptor will be passed every request and response. We will take that request and response
// and post a message to the window. This will allow us to access this message in the content script. This
// is all to make the manifest v3 happy.
const interceptor =
(next) =>
async (req) => {
return await next(req).then((resp) => {
if (!resp.stream) {
window.postMessage({
type: "__GRPCWEB_DEVTOOLS__",
methodType: "unary",
method: req.method.name,
request: req.message.toJson(),
response: resp.message.toJson(),
}, "*")
return resp;
} else {
return {
...resp,
async read() {
const streamResp = await resp.read();
// "value" could be undefined when "done" is true
if (streamResp.value) {
window.postMessage({
type: "__GRPCWEB_DEVTOOLS__",
methodType: "server_streaming",
method: req.method.name,
request: req.message.toJson(),
response: streamResp.value.toJson(),
}, "*");
}
return streamResp;
}
}
}
}).catch((e) => {
window.postMessage({
type: "__GRPCWEB_DEVTOOLS__",
methodType: req.stream ? "server_streaming" : "unary",
method: req.method.name,
request: req.message.toJson(),
response: undefined,
error: {
message: e.message,
code: e.code,
}
}, "*")
throw e;
});
};
/**
* Reads the message from the stream and posts it to the window.
* This is a generator function that will be passed to the response stream.
*/
async function* readMessage(req, stream) {
for await (const m of stream) {
if (m) {
const resp = m.toJson?.();
window.postMessage({
type: "__GRPCWEB_DEVTOOLS__",
methodType: "server_streaming",
method: req.method.name,
request: req.message.toJson?.(),
response: resp,
}, "*");
}
yield m;
}
}

/**
* This interceptor will be passed every request and response. We will take that request and response
* and post a message to the window. This will allow us to access this message in the content script. This
* is all to make the manifest v3 happy.
*/
const interceptor = (next) => async (req) => {
try {
const resp = await next(req);
if (!resp.stream) {
window.postMessage({
type: "__GRPCWEB_DEVTOOLS__",
methodType: "unary",
method: req.method.name,
request: req.message.toJson(),
response: resp.message.toJson(),
}, "*")
return resp;
} else {
return {
...resp,
message: readMessage(req, resp.message),
}
}
} catch (e) {
window.postMessage({
type: "__GRPCWEB_DEVTOOLS__",
methodType: req.stream ? "server_streaming" : "unary",
method: req.method.name,
request: req.message.toJson(),
response: undefined,
error: {
message: e.message,
code: e.code,
}
}, "*")
throw e;
}
};

window.__CONNECT_WEB_DEVTOOLS__ = interceptor;

// Since we are loading inject.js as a script, the order at which it is loaded is not guaranteed.
// So we will publish a custom event that can be used, to be used to assign the interceptor.
/**
* Since we are loading inject.js as a script, the order at which it is loaded is not guaranteed.
* So we will publish a custom event that can be used, to be used to assign the interceptor.
*/
const readyEvent = new CustomEvent("connect-web-dev-tools-ready");
window.dispatchEvent(readyEvent);
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gRPC-Web Developer Tools",
"version": "1.2.1",
"version": "1.4.0",
"manifest_version": 2,
"description": "gRPC-Web Developer Tools for debugging application's gRPC-Web network requests.",
"icons": {
Expand Down

0 comments on commit 3faf870

Please sign in to comment.