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

[TEX-537] Optional support for unframing grpc-web+json requests. #501

Conversation

timdawborn
Copy link
Contributor

@timdawborn timdawborn commented Sep 29, 2023

Add a new option for unframing application/grpc-web+json requests to be just application/json requests if the request is to a whitelisted hostname. This unframing is performed by mutating the received request before doing anything else with it, including passing it upstream or searching for existing tapes. This has the effect that, for all intents and purposes, the request is an application/json request for the purposes of persistence, similarity scoring, and proxying.

@timdawborn timdawborn force-pushed the TEX-537-optional-rewriting-of-grpc-web-json-requests-to-unframed-json branch from efa431c to 6faf81e Compare October 4, 2023 08:00
@timdawborn timdawborn requested review from a team, flavray and njday and removed request for a team October 4, 2023 08:05
@timdawborn timdawborn marked this pull request as ready for review October 4, 2023 08:05
Comment on lines +44 to +65
test("response: simple text", async () => {
const response = await axios.get(`${PROXAY_HOST}${SIMPLE_TEXT_PATH}`);
expect(response.data).toBe(SIMPLE_TEXT_RESPONSE);
});

test("response: utf-8", async () => {
const response = await axios.get(`${PROXAY_HOST}${UTF8_PATH}`);
expect(response.data).toBe(UTF8_RESPONSE);
});

test("response: binary", async () => {
const response = await axios.get(`${PROXAY_HOST}${BINARY_PATH}`, {
responseType: "arraybuffer",
});
expect(response.data).toEqual(BINARY_RESPONSE);
});

test("can pick any tape", async () => {
await axios.post(`${PROXAY_HOST}/__proxay/tape`, {
tape: "new-tape",
});
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all copies of the above tests, but with the proxay server running with unframing enabled. I duplicated these to ensure they weren't affected by running with unframing enabled.

Comment on lines +67 to +120
test("unframes a grpc-web+json request", async () => {
const requestBody = Buffer.from([
0,
0,
0,
0,
31,
123,
34,
101,
109,
97,
105,
108,
34,
58,
34,
102,
111,
111,
46,
98,
97,
114,
64,
101,
120,
97,
109,
112,
108,
101,
46,
99,
111,
109,
34,
125,
]);
const response = await axios.post(
`${PROXAY_HOST}${GRPC_WEB_JSON_PATH}`,
requestBody,
{
headers: {
"content-type": "application/grpc-web+json",
host: `localhost:${TEST_SERVER_PORT}`,
},
}
);
expect(response.headers["content-type"]).toBe(
"application/json; charset=utf-8"
);
expect(response.data).toEqual({ email: "foo.bar@example.com" });
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a new test for unframing.

Comment on lines -77 to -84
if (
this.preventConditionalRequests &&
(req.method === "GET" || req.method === "HEAD")
) {
// Headers are always coming in as lowercase.
delete req.headers["if-modified-since"];
delete req.headers["if-none-match"];
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this logic into the new rewriteRequest helper method that includes other potential request modifications.

Comment on lines +252 to +260
// Potentially prevent 304 responses from being able to be generated.
if (
this.preventConditionalRequests &&
(request.method === "GET" || request.method === "HEAD")
) {
// Headers are always coming in as lowercase.
delete request.headers["if-modified-since"];
delete request.headers["if-none-match"];
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moved logic.

Comment on lines +262 to +270
// Potentially unframe a grpc-web+json request.
if (
request.method === "POST" &&
request.headers["content-type"] === "application/grpc-web+json" &&
hostname != null &&
this.unframeGrpcWebJsonRequestsHostnames.includes(hostname)
) {
this.rewriteGrpcWebJsonRequest(request);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new logic.

@@ -78,6 +78,10 @@ async function main(argv: string[]) {
"--https-ca <filename.pem>",
"Enable HTTPS server where the certificate was generated by this CA. Useful if you are using a self-signed certificate. Also requires --https-key and --https-cert."
)
.option(
"--unframe-grpc-web-json-requests-hostname [hostname...]",
"Rewrite received requests whose content-type is application/grpc-web+json to be application/json, mutating the body of the request accordingly. This is useful if you want plain text tape records rather than binary data. The gRPC server needs to support receiving unframed requests for this option to be useful."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: We could also include the details about hostname matching in the description here

Copy link

@njday njday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link

@flavray flavray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sheep It

@timdawborn timdawborn merged commit e1bc576 into master Oct 5, 2023
5 checks passed
@timdawborn timdawborn deleted the TEX-537-optional-rewriting-of-grpc-web-json-requests-to-unframed-json branch October 5, 2023 03:01
timdawborn added a commit that referenced this pull request Oct 5, 2023
…sts (#503)

This is a small extension upon the functionality added in #501. This PR
extends the whitelist of hostnames to allow a `*` wildcard in order to
signify that any hostname should be allowed for `grpc-web+json`
unframing.
timdawborn added a commit that referenced this pull request Jan 5, 2024
Removes the functionality to unframe gRPC-web+json requests (added in
#501 and #503) in favour of the proper solution to handle grpc-web
requests in full (added in #548).

This functionality didn't work quite as expected anyway, so it's good to
clean it up in favour of the the full, proper working solution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants