From ae5126a8f386dd539e2f83e81bb06cb68894b88f Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 26 Mar 2024 10:09:51 +0300 Subject: [PATCH 1/2] feat: add ability to specify an array in expectedResponseContentType --- README.md | 3 ++- lib/components/rest.ts | 51 +++++++++++++++++++++++++----------------- lib/models/common.ts | 6 +++-- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b8e0abe..f33f97c 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ type ProxyHeadersFunction = ( type: ControllerType, ) => IncomingHttpHeaders; type ProxyHeaders = string[] | ProxyHeadersFunction; +type ResponseContentType = AxiosResponse['headers']['Content-Type']; interface GatewayConfig { // Gateway Installation (external/internal/...). If the configuration is not provided, it is determined from process.env.APP_INSTALLATION. @@ -119,7 +120,7 @@ interface GatewayConfig { // Configuration for automatic connection re-establishment upon connection error through L3 load balancer (default is true). grpcRecreateService?: boolean; // Enable verification of response contentType header. Actual only for REST actions. This value can be set / redefined the in action confg. - expectedResponseContentType?: AxiosResponse['headers']['Content-Type']; + expectedResponseContentType?: ResponseContentType | ResponseContentType[]; } ``` diff --git a/lib/components/rest.ts b/lib/components/rest.ts index 24b0c3a..61456f3 100644 --- a/lib/components/rest.ts +++ b/lib/components/rest.ts @@ -305,29 +305,38 @@ export default function createRestAction( const expectedResponseContentType = config.expectedResponseContentType || options.expectedResponseContentType; - if ( - actualResponseContentType && - expectedResponseContentType && - actualResponseContentType !== expectedResponseContentType - ) { - ctx.log('Invalid response content type', { - expectedResponseContentType, - actualResponseContentType, - }); - ctx.end(); + if (actualResponseContentType && expectedResponseContentType) { + let invalidResponseContentType; - return Promise.reject({ - error: { - status: 415, - message: 'Response content type validation failed', - code: 'INVALID_RESPONSE_CONTENT_TYPE', - details: { - title: 'Invalid response content type', - description: `Expected to get ${expectedResponseContentType} but got ${actualResponseContentType}`, + if (Array.isArray(expectedResponseContentType)) { + invalidResponseContentType = !expectedResponseContentType.includes( + String(actualResponseContentType), + ); + } else { + invalidResponseContentType = + expectedResponseContentType !== actualResponseContentType; + } + + if (invalidResponseContentType) { + ctx.log('Invalid response content type', { + expectedResponseContentType, + actualResponseContentType, + }); + ctx.end(); + + return Promise.reject({ + error: { + status: 415, + message: 'Response content type validation failed', + code: 'INVALID_RESPONSE_CONTENT_TYPE', + details: { + title: 'Invalid response content type', + description: `Expected to get ${expectedResponseContentType} but got ${actualResponseContentType}`, + }, }, - }, - debugHeaders, - }); + debugHeaders, + }); + } } if (config.transformResponseData) { diff --git a/lib/models/common.ts b/lib/models/common.ts index 61c66d1..8459bbf 100644 --- a/lib/models/common.ts +++ b/lib/models/common.ts @@ -100,6 +100,8 @@ export type GetAuthHeaders> = ( params: GetAuthHeadersParams, ) => Record | undefined; +export type ResponseContentType = AxiosResponse['headers']['Content-Type']; + export interface GatewayApiOptions { serviceName: string; timeout?: number; @@ -110,7 +112,7 @@ export interface GatewayApiOptions { proxyHeaders?: ProxyHeaders; validationSchema?: object; encodePathArgs?: boolean; - expectedResponseContentType?: AxiosResponse['headers']['Content-Type']; + expectedResponseContentType?: ResponseContentType | ResponseContentType[]; getAuthHeaders: GetAuthHeaders; } @@ -176,7 +178,7 @@ export interface ApiServiceRestActionConfig< path: (args: TParams) => string; paramsSerializer?: AxiosRequestConfig['paramsSerializer']; responseType?: AxiosRequestConfig['responseType']; - expectedResponseContentType?: AxiosResponse['headers']['Content-Type']; + expectedResponseContentType?: ResponseContentType | ResponseContentType[]; maxRedirects?: number; } From ea96334200e8fb5648e66a9a3a3c3ed05d51d818 Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 26 Mar 2024 18:45:38 +0300 Subject: [PATCH 2/2] fix: tune PR review --- lib/components/rest.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/components/rest.ts b/lib/components/rest.ts index 61456f3..9fbb759 100644 --- a/lib/components/rest.ts +++ b/lib/components/rest.ts @@ -306,18 +306,18 @@ export default function createRestAction( config.expectedResponseContentType || options.expectedResponseContentType; if (actualResponseContentType && expectedResponseContentType) { - let invalidResponseContentType; + let isInvalidResponseContentType; if (Array.isArray(expectedResponseContentType)) { - invalidResponseContentType = !expectedResponseContentType.includes( + isInvalidResponseContentType = !expectedResponseContentType.includes( String(actualResponseContentType), ); } else { - invalidResponseContentType = + isInvalidResponseContentType = expectedResponseContentType !== actualResponseContentType; } - if (invalidResponseContentType) { + if (isInvalidResponseContentType) { ctx.log('Invalid response content type', { expectedResponseContentType, actualResponseContentType,