Skip to content

Commit

Permalink
Allow user-provided User-Agent request header (#1272)
Browse files Browse the repository at this point in the history
  • Loading branch information
polRk authored Oct 28, 2024
1 parent 075f0e1 commit 92dcc1a
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 16 deletions.
8 changes: 4 additions & 4 deletions packages/connect-web-bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ usually do. We repeat this for an increasing number of RPCs.

| code generator | RPCs | bundle size | minified | compressed |
| -------------- | ---: | ----------: | --------: | ---------: |
| Connect-ES | 1 | 276,211 b | 176,242 b | 35,720 b |
| Connect-ES | 4 | 280,463 b | 179,344 b | 36,504 b |
| Connect-ES | 8 | 285,326 b | 183,775 b | 37,426 b |
| Connect-ES | 16 | 294,454 b | 191,399 b | 38,961 b |
| Connect-ES | 1 | 276,243 b | 176,254 b | 35,712 b |
| Connect-ES | 4 | 280,495 b | 179,356 b | 36,466 b |
| Connect-ES | 8 | 285,358 b | 183,787 b | 37,481 b |
| Connect-ES | 16 | 294,486 b | 191,411 b | 38,982 b |
| gRPC-Web | 1 | 876,563 b | 548,495 b | 52,300 b |
| gRPC-Web | 4 | 928,964 b | 580,477 b | 54,673 b |
| gRPC-Web | 8 | 1,004,833 b | 628,223 b | 57,118 b |
Expand Down
10 changes: 5 additions & 5 deletions packages/connect-web-bench/chart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions packages/connect/src/protocol-connect/request-header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ describe("requestHeader", () => {
expect(headers.get("Connect-Timeout-Ms")).toBe("10");
});

it("should create request headers with user provided user-agent", () => {
const headers = requestHeader(
"unary",
true,
10,
{ "User-Agent": "grpc-es/0.0.0" },
true,
);
expect(listHeaderKeys(headers)).toEqual([
"connect-protocol-version",
"connect-timeout-ms",
"content-type",
"user-agent",
]);
expect(headers.get("User-Agent")).toBe("grpc-es/0.0.0");
});

it("should exclude user-agent", () => {
const headers = requestHeader("unary", true, undefined, undefined, false);
expect(listHeaderKeys(headers)).toEqual([
Expand Down
7 changes: 6 additions & 1 deletion packages/connect/src/protocol-connect/request-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,14 @@ export function requestHeader(
: contentTypeStreamJson,
);
result.set(headerProtocolVersion, protocolVersion);
if (setUserAgent) {

if (!result.has(headerUserAgent) && setUserAgent) {
// Note that we do not strictly comply with gRPC user agents.
// We use "connect-es/1.2.3" where gRPC would use "grpc-es/1.2.3".
// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headerUserAgent, "CONNECT_ES_USER_AGENT");
}

return result;
}

Expand Down
36 changes: 36 additions & 0 deletions packages/connect/src/protocol-grpc-web/request-header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,42 @@ describe("requestHeader", () => {
expect(headers.get("Grpc-Timeout")).toBe("10m");
});

it("should set user provided user-agent header", () => {
const headers = requestHeader(
true,
10,
{ "User-Agent": "grpc-es/0.0.0" },
true,
);
expect(listHeaderKeys(headers)).toEqual([
"content-type",
"grpc-timeout",
"user-agent",
"x-grpc-web",
"x-user-agent",
]);
expect(headers.get("User-Agent")).toBe("grpc-es/0.0.0");
expect(headers.get("X-User-Agent")).toBe("grpc-es/0.0.0");
});

it("should set user provided x-user-agent header", () => {
const headers = requestHeader(
true,
10,
{ "X-User-Agent": "grpc-es/0.0.0" },
true,
);
expect(listHeaderKeys(headers)).toEqual([
"content-type",
"grpc-timeout",
"user-agent",
"x-grpc-web",
"x-user-agent",
]);
expect(headers.get("User-Agent")).toBe("grpc-es/0.0.0");
expect(headers.get("X-User-Agent")).toBe("grpc-es/0.0.0");
});

it("should create request headers with compression", () => {
const compressionMock: Compression = {
name: "gzip",
Expand Down
11 changes: 9 additions & 2 deletions packages/connect/src/protocol-grpc-web/request-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,16 @@ export function requestHeader(
// Note that we do not strictly comply with gRPC user agents.
// We use "connect-es/1.2.3" where gRPC would use "grpc-es/1.2.3".
// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headerXUserAgent, "CONNECT_ES_USER_AGENT");
let userAgent = "CONNECT_ES_USER_AGENT";
userAgent = result.has(headerUserAgent)
? result.get(headerUserAgent)!
: result.has(headerXUserAgent)
? result.get(headerXUserAgent)!
: userAgent;

result.set(headerXUserAgent, userAgent);
if (setUserAgent) {
result.set(headerUserAgent, "CONNECT_ES_USER_AGENT");
result.set(headerUserAgent, userAgent);
}
if (timeoutMs !== undefined) {
result.set(headerTimeout, `${timeoutMs}m`);
Expand Down
11 changes: 11 additions & 0 deletions packages/connect/src/protocol-grpc/request-header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ describe("requestHeader", () => {
expect(headers.get("Grpc-Timeout")).toBe("10m");
});

it("should create request headers with user provided user-agent", () => {
const headers = requestHeader(true, 10, { "User-Agent": "grpc-es/0.0.0" });
expect(listHeaderKeys(headers)).toEqual([
"content-type",
"grpc-timeout",
"te",
"user-agent",
]);
expect(headers.get("User-Agent")).toBe("grpc-es/0.0.0");
});

it("should create request headers with compression", () => {
const compressionMock: Compression = {
name: "gzip",
Expand Down
13 changes: 9 additions & 4 deletions packages/connect/src/protocol-grpc/request-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,18 @@ export function requestHeader(
headerContentType,
useBinaryFormat ? contentTypeProto : contentTypeJson,
);
// Note that we do not strictly comply with gRPC user agents.
// We use "connect-es/1.2.3" where gRPC would use "grpc-es/1.2.3".
// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headerUserAgent, "CONNECT_ES_USER_AGENT");

if (!result.has(headerUserAgent)) {
// Note that we do not strictly comply with gRPC user agents.
// We use "connect-es/1.2.3" where gRPC would use "grpc-es/1.2.3".
// See https://github.com/grpc/grpc/blob/c462bb8d485fc1434ecfae438823ca8d14cf3154/doc/PROTOCOL-HTTP2.md#user-agents
result.set(headerUserAgent, "CONNECT_ES_USER_AGENT");
}

if (timeoutMs !== undefined) {
result.set(headerTimeout, `${timeoutMs}m`);
}

// The gRPC-HTTP2 specification requires this - it flushes out proxies that
// don't support HTTP trailers.
result.set("Te", "trailers");
Expand Down

0 comments on commit 92dcc1a

Please sign in to comment.