From 5377bff4e751c9ece766e8b6f9a28e53d94eac0d Mon Sep 17 00:00:00 2001 From: Lennart Klose Date: Thu, 6 Jun 2024 16:52:57 +0200 Subject: [PATCH 1/4] Add contextMiddlewareFactoryWithFixedSystemBaseUri-function --- .../dvelop-context-middleware.ts | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts index 1838a6f9..45f9a77f 100644 --- a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts +++ b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts @@ -18,17 +18,27 @@ import { Request, Response, NextFunction } from "express"; */ export function contextMiddlewareFactory( parseTraceparentHeader: (traceparentHeader: string) => TraceContext, - generateTraceContext: () => TraceContext + generateTraceContext: () => TraceContext, + systemBaseUri?: string, + tenantId?: string ): (req: Request, _: Response, next: NextFunction) => void { return (req: Request, _: Response, next: NextFunction) => { - req.dvelopContext = { - systemBaseUri: req.header(DVELOP_SYSTEM_BASE_URI_HEADER), - tenantId: req.header(DVELOP_TENANT_ID_HEADER), - requestId: req.header(DVELOP_REQUEST_ID_HEADER), - requestSignature: req.header(DVELOP_REQUEST_SIGNATURE_HEADER), - }; + if (systemBaseUri && tenantId) { + req.dvelopContext = { + systemBaseUri: systemBaseUri, + tenantId: tenantId, + requestId: req.header(DVELOP_REQUEST_ID_HEADER) + } + } else { + req.dvelopContext = { + systemBaseUri: req.header(DVELOP_SYSTEM_BASE_URI_HEADER), + tenantId: req.header(DVELOP_TENANT_ID_HEADER), + requestId: req.header(DVELOP_REQUEST_ID_HEADER), + requestSignature: req.header(DVELOP_REQUEST_SIGNATURE_HEADER), + }; + } const traceparentHeader = req.header(TRACEPARENT_HEADER); @@ -66,3 +76,27 @@ export function contextMiddlewareFactory( export function contextMiddleware(req: Request, _: Response, next: NextFunction): void { return contextMiddlewareFactory(parseTraceparentHeader, generateTraceContext)(req, _, next); } + +/** + * Sets a {@link DvelopContext} to the express-request-object. Accessable via the ```req.dvelopContext```-property. + * This is a version with a fixed systemBaseUri, primarily used on premise. + * + * ```typescript + * import { contextMiddleware } from "@dvelop-sdk/express-utils"; + * + * app.use(contextMiddleware); + * + * app.use((req: Request, _: Response, next: NextFunction) => { + * console.log(req.dvelopContext); + * next(); + * }); + * ``` + * + * @category Middleware + */ +/* istanbul ignore next */ +export function contextMiddlewareFactoryWithFixedSystemBaseUri(systemBaseUri: string, tenantId: string = "0") { + return (req: Request, _: Response, next: NextFunction) => { + return contextMiddlewareFactory(parseTraceparentHeader, generateTraceContext, systemBaseUri, tenantId)(req, _, next); + } +} From 46cf55022952719ee508661594b6804ded43b2d2 Mon Sep 17 00:00:00 2001 From: Lennart Klose Date: Fri, 7 Jun 2024 09:06:05 +0200 Subject: [PATCH 2/4] Add test for contextMiddlewareFactoryWithFixedSystemBaseUri-function --- .../dvelop-context-middleware.spec.ts | 199 ++++++++++++------ .../dvelop-context-middleware.ts | 4 +- 2 files changed, 135 insertions(+), 68 deletions(-) diff --git a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.spec.ts b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.spec.ts index 7ae1f681..8041f11f 100644 --- a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.spec.ts +++ b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.spec.ts @@ -30,44 +30,110 @@ describe("contextMiddlewareFactory", () => { mockRes = {} as unknown as Response; }); - it("should set context", () => { + describe("dvelopContext", () => { + it("should set context from headers on no systemBaseUri", () => { - const systemBaseUri: string = "HiItsMeSystemBaseUri"; - const tenantId: string = "HiItsMeTenantId"; - const requestId: string = "HiItsMeRequestId"; - const requestSignature: string = "HiItsMeRequestSignature"; + const systemBaseUri: string = "HiItsMeSystemBaseUri"; + const tenantId: string = "HiItsMeTenantId"; + const requestId: string = "HiItsMeRequestId"; + const requestSignature: string = "HiItsMeRequestSignature"; - (mockReq.header as jest.Mock).mockImplementation((header: string) => { - switch (header) { - case DVELOP_SYSTEM_BASE_URI_HEADER: - return systemBaseUri; + (mockReq.header as jest.Mock).mockImplementation((header: string) => { + switch (header) { + case DVELOP_SYSTEM_BASE_URI_HEADER: + return systemBaseUri; - case DVELOP_TENANT_ID_HEADER: - return tenantId; + case DVELOP_TENANT_ID_HEADER: + return tenantId; - case DVELOP_REQUEST_ID_HEADER: - return requestId; + case DVELOP_REQUEST_ID_HEADER: + return requestId; - case DVELOP_REQUEST_SIGNATURE_HEADER: - return requestSignature; + case DVELOP_REQUEST_SIGNATURE_HEADER: + return requestSignature; - case TRACEPARENT_HEADER: - return undefined; + case TRACEPARENT_HEADER: + return undefined; + + default: + throw "No other should be requested"; + } + }); + + contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext)(mockReq, mockRes, mockNext); - default: - throw "No other should be requested"; - } + expect(mockReq.dvelopContext).toEqual(expect.objectContaining({ + systemBaseUri: systemBaseUri, + tenantId: tenantId, + requestId: requestId, + requestSignature: requestSignature, + traceContext: undefined + })); }); - contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext)(mockReq, mockRes, mockNext); + it("should not set systemBaseUri and tenantId from input if provided", () => { + + const systemBaseUri: string = "HiItsMeSystemBaseUri"; + const tenantId: string = "HiItsMeTenantId"; + const requestId: string = "HiItsMeRequestId"; + + (mockReq.header as jest.Mock).mockImplementation((header: string) => { + switch (header) { + + case DVELOP_REQUEST_ID_HEADER: + return requestId; + + case TRACEPARENT_HEADER: + return undefined; + + default: + throw "No other should be requested"; + } + }); + + contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext, systemBaseUri, tenantId)(mockReq, mockRes, mockNext); + + expect(mockReq.dvelopContext).toEqual(expect.objectContaining({ + systemBaseUri: systemBaseUri, + tenantId: tenantId, + requestId: requestId, + traceContext: undefined + })); + }); + + it("should set systemBaseUri from input and tenantId from headers if only systemBaseUri is provided", () => { + + const systemBaseUri: string = "HiItsMeSystemBaseUri"; + const tenantId: string = "HiItsMeTenantId"; + const requestId: string = "HiItsMeRequestId"; + const requestSignature: string = "HiItsMeRequestSignature"; + + (mockReq.header as jest.Mock).mockImplementation((header: string) => { + switch (header) { + + case DVELOP_TENANT_ID_HEADER: + return tenantId; + + case DVELOP_REQUEST_ID_HEADER: + return requestId; + + case TRACEPARENT_HEADER: + return undefined; - expect(mockReq.dvelopContext).toEqual(expect.objectContaining({ - systemBaseUri: systemBaseUri, - tenantId: tenantId, - requestId: requestId, - requestSignature: requestSignature, - traceContext: undefined - })); + default: + throw "No other should be requested"; + } + }); + + contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext, systemBaseUri)(mockReq, mockRes, mockNext); + + expect(mockReq.dvelopContext).toEqual(expect.objectContaining({ + systemBaseUri: systemBaseUri, + tenantId: tenantId, + requestId: requestId, + traceContext: undefined + })); + }); }); describe("traceContext", () => { @@ -79,10 +145,10 @@ describe("contextMiddlewareFactory", () => { (mockReq.header as jest.Mock).mockImplementation((header: string) => { switch (header) { - case TRACEPARENT_HEADER: - return traceparentHeader; - default: - return "HiItsMeHeader"; + case TRACEPARENT_HEADER: + return traceparentHeader; + default: + return "HiItsMeHeader"; } }); @@ -92,52 +158,53 @@ describe("contextMiddlewareFactory", () => { expect(mockParseTraceparentHeader).toHaveBeenCalledWith(traceparentHeader); expect(mockGenerateTraceContext).toHaveBeenCalledTimes(0); }); - }); - it("should generate traceContext on no traceparent-header", () => { + it("should generate traceContext on no traceparent-header", () => { + + const traceContext: TraceContext = { traceId: "traceId" } as TraceContext; + mockGenerateTraceContext.mockReturnValue(traceContext); + + (mockReq.header as jest.Mock).mockImplementation((header: string) => { + switch (header) { + case TRACEPARENT_HEADER: + return undefined; + default: + return "HiItsMeHeader"; + } + }); - const traceContext: TraceContext = { traceId: "traceId" } as TraceContext; - mockGenerateTraceContext.mockReturnValue(traceContext); + contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext)(mockReq, mockRes, mockNext); - (mockReq.header as jest.Mock).mockImplementation((header: string) => { - switch (header) { - case TRACEPARENT_HEADER: - return undefined; - default: - return "HiItsMeHeader"; - } + expect(mockReq.dvelopContext.traceContext).toEqual(traceContext); + expect(mockParseTraceparentHeader).toHaveBeenCalledTimes(0); + expect(mockGenerateTraceContext).toHaveBeenCalledTimes(1); }); - contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext)(mockReq, mockRes, mockNext); + it("should generate traceContext on traceparent-header parsing error", () => { - expect(mockReq.dvelopContext.traceContext).toEqual(traceContext); - expect(mockParseTraceparentHeader).toHaveBeenCalledTimes(0); - expect(mockGenerateTraceContext).toHaveBeenCalledTimes(1); - }); + const traceparentHeader: string = "HiItsMeTraceparentHeader"; + mockParseTraceparentHeader.mockImplementation((_: string) => { throw new TraceContextError(""); }); - it("should generate traceContext on traceparent-header parsing error", () => { + const traceContext: TraceContext = { traceId: "traceId" } as TraceContext; + mockGenerateTraceContext.mockReturnValue(traceContext); - const traceparentHeader: string = "HiItsMeTraceparentHeader"; - mockParseTraceparentHeader.mockImplementation((_: string) => { throw new TraceContextError(""); }); + (mockReq.header as jest.Mock).mockImplementation((header: string) => { + switch (header) { + case TRACEPARENT_HEADER: + return traceparentHeader; + default: + return "HiItsMeHeader"; + } + }); - const traceContext: TraceContext = { traceId: "traceId" } as TraceContext; - mockGenerateTraceContext.mockReturnValue(traceContext); + contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext)(mockReq, mockRes, mockNext); - (mockReq.header as jest.Mock).mockImplementation((header: string) => { - switch (header) { - case TRACEPARENT_HEADER: - return traceparentHeader; - default: - return "HiItsMeHeader"; - } + expect(mockReq.dvelopContext.traceContext).toEqual(traceContext); + expect(mockParseTraceparentHeader).toHaveBeenCalledTimes(1); + expect(mockParseTraceparentHeader).toHaveBeenCalledWith(traceparentHeader); + expect(mockGenerateTraceContext).toHaveBeenCalledTimes(1); }); - contextMiddlewareFactory(mockParseTraceparentHeader, mockGenerateTraceContext)(mockReq, mockRes, mockNext); - - expect(mockReq.dvelopContext.traceContext).toEqual(traceContext); - expect(mockParseTraceparentHeader).toHaveBeenCalledTimes(1); - expect(mockParseTraceparentHeader).toHaveBeenCalledWith(traceparentHeader); - expect(mockGenerateTraceContext).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts index 45f9a77f..9b46e7cf 100644 --- a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts +++ b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts @@ -25,10 +25,10 @@ export function contextMiddlewareFactory( return (req: Request, _: Response, next: NextFunction) => { - if (systemBaseUri && tenantId) { + if (systemBaseUri) { req.dvelopContext = { systemBaseUri: systemBaseUri, - tenantId: tenantId, + tenantId: tenantId || req.header(DVELOP_TENANT_ID_HEADER), requestId: req.header(DVELOP_REQUEST_ID_HEADER) } } else { From 74fe76bec8e95cc7647856909692e012fe97c74a Mon Sep 17 00:00:00 2001 From: Lennart Klose Date: Fri, 7 Jun 2024 09:06:55 +0200 Subject: [PATCH 3/4] Raise version for @dvelop-sdk/express-utils --- packages/express-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/express-utils/package.json b/packages/express-utils/package.json index 21109fd9..73b4cfd5 100644 --- a/packages/express-utils/package.json +++ b/packages/express-utils/package.json @@ -1,7 +1,7 @@ { "name": "@dvelop-sdk/express-utils", "description": "This package contains middleware-functions for the express-framework and d.velop app-building.", - "version": "1.1.8", + "version": "1.2.0", "license": "Apache-2.0", "main": "lib/index.js", "types": "lib/index.d.ts", From e28a5c5445c7169378f166be31cd7f2cc69d9f69 Mon Sep 17 00:00:00 2001 From: Lennart Klose Date: Fri, 7 Jun 2024 09:11:33 +0200 Subject: [PATCH 4/4] Update docs --- .../dvelop-context-middleware/dvelop-context-middleware.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts index 9b46e7cf..0038cbe8 100644 --- a/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts +++ b/packages/express-utils/src/middleware/dvelop-context-middleware/dvelop-context-middleware.ts @@ -82,9 +82,9 @@ export function contextMiddleware(req: Request, _: Response, next: NextFunction) * This is a version with a fixed systemBaseUri, primarily used on premise. * * ```typescript - * import { contextMiddleware } from "@dvelop-sdk/express-utils"; + * import { contextMiddlewareFactoryWithFixedSystemBaseUri } from "@dvelop-sdk/express-utils"; * - * app.use(contextMiddleware); + * app.use(contextMiddlewareFactoryWithFixedSystemBaseUri("https://my.local.baseuri")); //could optionally supply a tenantId (default: 0) * * app.use((req: Request, _: Response, next: NextFunction) => { * console.log(req.dvelopContext);