From 97c462264680b3c8618a11d2d0195ac0184cdf2f Mon Sep 17 00:00:00 2001 From: Steve Ayers Date: Fri, 24 Jan 2025 14:14:12 -0500 Subject: [PATCH] Ensure any error metadata is appended to target grpc response Signed-off-by: Steve Ayers --- .../src/protocol-grpc/trailer-status.spec.ts | 30 +++++++++++++++++++ .../src/protocol-grpc/trailer-status.ts | 7 +++++ 2 files changed, 37 insertions(+) diff --git a/packages/connect/src/protocol-grpc/trailer-status.spec.ts b/packages/connect/src/protocol-grpc/trailer-status.spec.ts index 9ae0a348c..44a01c6c3 100644 --- a/packages/connect/src/protocol-grpc/trailer-status.spec.ts +++ b/packages/connect/src/protocol-grpc/trailer-status.spec.ts @@ -63,6 +63,36 @@ describe("setTrailerStatus()", function () { "CAgSDHNvaXLDqWUg8J+OiRo0Ci50eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlEgIIew", ); }); + it("should append any error metadata", function () { + const t = new Headers(); + setTrailerStatus( + t, + new ConnectError("soirée 🎉", Code.ResourceExhausted, { foo: "bar" }), + ); + let count = 0; + t.forEach(() => count++); + expect(count).toBe(3); + expect(t.get("grpc-status")).toBe("8"); // resource_exhausted + expect(t.get("grpc-message")).toBe("soir%C3%A9e%20%F0%9F%8E%89"); + expect(t.get("foo")).toBe("bar"); + }); + it("should overwrite error metadata that uses reserved protocol headers", function () { + const t = new Headers(); + setTrailerStatus( + t, + new ConnectError("soirée 🎉", Code.ResourceExhausted, { + foo: "bar", + "grpc-status": "foo-status", + "grpc-message": "foo-message", + }), + ); + let count = 0; + t.forEach(() => count++); + expect(count).toBe(3); + expect(t.get("grpc-status")).toBe("8"); // resource_exhausted + expect(t.get("grpc-message")).toBe("soir%C3%A9e%20%F0%9F%8E%89"); + expect(t.get("foo")).toBe("bar"); + }); }); describe("findTrailerError()", function () { diff --git a/packages/connect/src/protocol-grpc/trailer-status.ts b/packages/connect/src/protocol-grpc/trailer-status.ts index 55a4cddd4..dfd1d8192 100644 --- a/packages/connect/src/protocol-grpc/trailer-status.ts +++ b/packages/connect/src/protocol-grpc/trailer-status.ts @@ -46,6 +46,13 @@ export function setTrailerStatus( error: ConnectError | undefined, ): Headers { if (error) { + // Copy any metadata specified in the error into the target Headers + // Note that if a protocol header happens to be specified in metadata, it + // its value will be overridden below by the official protocol headers. + error.metadata.forEach((value, key) => { + target.append(key, value); + }); + target.set(headerGrpcStatus, error.code.toString(10)); target.set(headerGrpcMessage, encodeURIComponent(error.rawMessage)); if (error.details.length > 0) {