Skip to content

Commit

Permalink
refactor(@whook/router): use multiple headers values everywhere
Browse files Browse the repository at this point in the history
fix #93
  • Loading branch information
nfroidure committed Dec 20, 2022
1 parent d3da046 commit 3a17640
Show file tree
Hide file tree
Showing 23 changed files with 264 additions and 108 deletions.
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/whook-aws-lambda/src/wrappers/awsConsumerLambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type ConsumerWrapperDependencies = {
};

export default function wrapHandlerForAWSConsumerLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand All @@ -70,7 +70,7 @@ export default function wrapHandlerForAWSConsumerLambda<
}

async function initHandlerForAWSConsumerLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(initHandler: ServiceInitializer<D, S>, services: D): Promise<S> {
const handler: S = await initHandler(services);
Expand Down
4 changes: 2 additions & 2 deletions packages/whook-aws-lambda/src/wrappers/awsCronLambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export type LambdaCronInput<T extends JsonObject = JsonObject> = {
export type LambdaCronOutput = WhookResponse<number, WhookHeaders, void>;

export default function wrapHandlerForAWSCronLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand All @@ -47,7 +47,7 @@ export default function wrapHandlerForAWSCronLambda<
}

async function initHandlerForAWSCronLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(initHandler: ServiceInitializer<D, S>, services: D): Promise<S> {
const handler: S = await initHandler(services);
Expand Down
29 changes: 18 additions & 11 deletions packages/whook-aws-lambda/src/wrappers/awsHTTPLambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ import type {
import type { TimeService, LogService } from 'common-services';
import type { OpenAPIV3 } from 'openapi-types';
import type { Readable } from 'stream';
import type { DereferencedParameterObject } from '@whook/http-transaction';
import {
DereferencedParameterObject,
pickAllHeaderValues,
} from '@whook/http-transaction';
import type {
APIGatewayProxyEvent,
APIGatewayProxyResult,
Expand Down Expand Up @@ -85,7 +88,7 @@ const uuidPattern =
'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$';

export default function wrapHandlerForAWSHTTPLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand Down Expand Up @@ -119,7 +122,7 @@ export default function wrapHandlerForAWSHTTPLambda<
}

async function initHandlerForAWSHTTPLambda(
initHandler: ServiceInitializer<Dependencies<any>, WhookHandler>,
initHandler: ServiceInitializer<Dependencies, WhookHandler>,
{
OPERATION_API,
WRAPPERS,
Expand Down Expand Up @@ -434,15 +437,16 @@ async function handleForAWSHTTPLambda(
}),
);

const transactionId =
pickAllHeaderValues('x-transaction-id', request.headers).filter((value) =>
new RegExp(uuidPattern).test(value),
)[0] ||
event.requestContext.requestId ||
'no_id';

apm('CALL', {
id: event.requestContext.requestId,
transactionId:
(request.headers['x-transaction-id'] &&
new RegExp(uuidPattern).test(
request.headers['x-transaction-id'] as string,
)
? event.headers['x-transaction-id']
: event.requestContext.requestId) || 'no_id',
transactionId,
environment: NODE_ENV,
method: event.requestContext.httpMethod,
resourcePath: event.requestContext.resourcePath,
Expand Down Expand Up @@ -494,7 +498,10 @@ async function awsRequestEventToRequest(
);
const request: WhookRequest = {
method: event.requestContext.httpMethod.toLowerCase(),
headers: lowerCaseHeaders(event.headers as Record<string, string>),
headers: lowerCaseHeaders({
...event.headers,
...event.multiValueHeaders,
}) as Record<string, string | string[]>,
url:
event.requestContext.path +
(queryStringParametersNames.length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export type LambdaKafkaConsumerOutput = WhookResponse<
>;

export default function wrapHandlerForAWSKafkaConsumerLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand All @@ -47,7 +47,7 @@ export default function wrapHandlerForAWSKafkaConsumerLambda<
}

async function initHandlerForAWSKafkaConsumerLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(initHandler: ServiceInitializer<D, S>, services: D): Promise<S> {
const handler: S = await initHandler(services);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type LogSubscriberWrapperDependencies = {
// Allow to subscribe to AWS logs
// See https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html
export default function wrapHandlerForAWSLogSubscriberLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand All @@ -55,7 +55,7 @@ export default function wrapHandlerForAWSLogSubscriberLambda<
}

async function initHandlerForAWSLogSubscriberLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(initHandler: ServiceInitializer<D, S>, services: D): Promise<S> {
const handler: S = await initHandler(services);
Expand Down
4 changes: 2 additions & 2 deletions packages/whook-aws-lambda/src/wrappers/awsS3Lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type LambdaS3Input = { body: S3Event['Records'] };
export type LambdaS3Output = WhookResponse<number, WhookHeaders, void>;

export default function wrapHandlerForAWSS3Lambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand All @@ -43,7 +43,7 @@ export default function wrapHandlerForAWSS3Lambda<
}

async function initHandlerForAWSS3Lambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(initHandler: ServiceInitializer<D, S>, services: D): Promise<S> {
const handler: S = await initHandler(services);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export type LambdaTransformerOutput = WhookResponse<
// See https://aws.amazon.com/fr/blogs/compute/amazon-kinesis-firehose-data-transformation-with-aws-lambda/
// See https://docs.aws.amazon.com/firehose/latest/dev/data-transformation.html
export default function wrapHandlerForAWSTransformerLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand All @@ -71,7 +71,7 @@ export default function wrapHandlerForAWSTransformerLambda<
}

async function initHandlerForAWSTransformerLambda<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(initHandler: ServiceInitializer<D, S>, services: D): Promise<S> {
const handler: S = await initHandler(services);
Expand Down
2 changes: 1 addition & 1 deletion packages/whook-cors/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export type WhookAPIOperationCORSConfig = {
* @returns {Function} The handler initializer wrapped
*/
export function wrapHandlerWithCORS<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const SEARCH_SEPARATOR = '?';
const PATH_SEPARATOR = '/';

export default function wrapHandlerForAWSHTTPFunction<
D extends Dependencies<any>,
D extends Dependencies,
S extends WhookHandler,
>(
initHandler: ServiceInitializer<D, S>,
Expand Down Expand Up @@ -98,7 +98,7 @@ export default function wrapHandlerForAWSHTTPFunction<
}

async function initHandlerForAWSHTTPFunction(
initHandler: ServiceInitializer<Dependencies<any>, WhookHandler>,
initHandler: ServiceInitializer<Dependencies, WhookHandler>,
{
OPERATION_API,
WRAPPERS,
Expand Down
2 changes: 1 addition & 1 deletion packages/whook-graphiql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export type WhookGraphIQLDependencies = WhookGraphIQLConfig & {
* @param {Function} initHTTPRouter The `httpRouter` initializer
* @returns {Function} The `httpRouter` initializer wrapped
*/
export default function wrapHTTPRouterWithGraphIQL<D extends Dependencies<any>>(
export default function wrapHTTPRouterWithGraphIQL<D extends Dependencies>(
initHTTPRouter: ProviderInitializer<D, HTTPRouterService>,
): ProviderInitializer<WhookGraphIQLDependencies & D, HTTPRouterService> {
const augmentedInitializer = alsoInject<
Expand Down
2 changes: 2 additions & 0 deletions packages/whook-http-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@
"homepage": "https://github.com/nfroidure/whook",
"dependencies": {
"@apidevtools/swagger-parser": "^10.1.0",
"@types/content-type": "^1.1.5",
"@types/qs": "^6.9.7",
"@types/negotiator": "^0.6.1",
"@whook/http-transaction": "^11.0.1",
"ajv": "^8.11.2",
"ajv-formats": "^2.1.1",
Expand Down
24 changes: 12 additions & 12 deletions packages/whook-http-router/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Siso } from 'siso';
import Ajv from 'ajv';
import addAJVFormats from 'ajv-formats';
import { qsStrict as strictQs } from 'strict-qs';
import { pickFirstHeaderValue } from '@whook/http-transaction';
import {
OPEN_API_METHODS,
flattenOpenAPI,
Expand Down Expand Up @@ -446,29 +447,28 @@ async function initHTTPRouter({
response.headers['content-type'] || responseSpec.contentTypes[0];
}

const responseContentType =
pickFirstHeaderValue('content-type', response.headers || {}) ||
'text/plain';

// Check the stringifyer only when a schema is
// specified and it is not a binary one
const responseHasSchema =
operation.responses &&
operation.responses[response.status] &&
operation.responses[response.status].content &&
operation.responses[response.status].content?.[
response.headers['content-type'] as string
responseContentType
] &&
operation.responses[response.status].content?.[
response.headers['content-type'] as string
].schema &&
(operation.responses[response.status].content?.[
response.headers['content-type'] as string
].schema.type !== 'string' ||
operation.responses[response.status].content?.[responseContentType]
.schema &&
(operation.responses[response.status].content?.[responseContentType]
.schema.type !== 'string' ||
operation.responses[response.status].content?.[
response.headers['content-type'] as string
responseContentType
].schema.format !== 'binary');

if (
responseHasSchema &&
!STRINGIFYERS[response.headers['content-type'] as string]
) {
if (responseHasSchema && !STRINGIFYERS[responseContentType]) {
throw new YHTTPError(
500,
'E_STRINGIFYER_LACK',
Expand Down
16 changes: 11 additions & 5 deletions packages/whook-http-router/src/libs/body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { YHTTPError } from 'yhttperror';
import FirstChunkStream from 'first-chunk-stream';
import Stream from 'stream';
import { YError } from 'yerror';
import type { WhookOperation, WhookResponse } from '@whook/http-transaction';
import {
pickFirstHeaderValue,
WhookOperation,
WhookResponse,
} from '@whook/http-transaction';
import type { BodySpec } from './utils.js';
import type { OpenAPIV3 } from 'openapi-types';
import type { JsonValue } from 'type-fest';
Expand Down Expand Up @@ -157,7 +161,11 @@ export async function sendBody(
return response;
}

if (!STRINGIFYERS?.[response.headers?.['content-type'] as string]) {
const responseContentType =
pickFirstHeaderValue('content-type', response.headers || {}) ||
'text/plain';

if (!STRINGIFYERS?.[responseContentType]) {
throw new YError(
'E_STRINGIFYER_LACK',
response.headers?.['content-type'],
Expand All @@ -172,9 +180,7 @@ export async function sendBody(
}

const stream = new Encoder();
const content = STRINGIFYERS[response.headers?.['content-type'] as string](
response.body as string,
);
const content = STRINGIFYERS[responseContentType](response.body as string);

stream.write(content);

Expand Down
Loading

0 comments on commit 3a17640

Please sign in to comment.