Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions packages/event-handler/src/rest/Router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class Router {
* Registers a custom error handler for specific error types.
*
* @param errorType - The error constructor(s) to handle
* @param handler - The error handler function that returns an ErrorResponse
* @param handler - The error handler that returns an error response
*/
public errorHandler<T extends Error>(
errorType: ErrorConstructor<T> | ErrorConstructor<T>[],
Expand All @@ -106,7 +106,8 @@ class Router {
/**
* Registers a custom handler for 404 Not Found errors.
*
* @param handler - The error handler function for NotFoundError
* @param handler - The error handler that returns an error
* response
*/
public notFound(handler: ErrorHandler<NotFoundError>): void;
public notFound(): MethodDecorator;
Expand All @@ -127,7 +128,7 @@ class Router {
/**
* Registers a custom handler for 405 Method Not Allowed errors.
*
* @param handler - The error handler function for MethodNotAllowedError
* @param handler - The error handler that returns an error response
*/
public methodNotAllowed(handler: ErrorHandler<MethodNotAllowedError>): void;
public methodNotAllowed(): MethodDecorator;
Expand Down Expand Up @@ -158,9 +159,9 @@ class Router {
*
* @example
* ```typescript
* const authMiddleware: Middleware = async (params, options, next) => {
* const authMiddleware: Middleware = async (params, reqCtx, next) => {
* // Authentication logic
* if (!isAuthenticated(options.request)) {
* if (!isAuthenticated(reqCtx.request)) {
* return new Response('Unauthorized', { status: 401 });
* }
* await next();
Expand Down Expand Up @@ -211,12 +212,12 @@ class Router {

const request = proxyEventToWebRequest(event);

const handlerOptions: RequestContext = {
const requestContext: RequestContext = {
event,
context,
request,
// this response should be overwritten by the handler, if it isn't
// it means somthing went wrong with the middleware chain
// it means something went wrong with the middleware chain
res: new Response('', { status: 500 }),
};

Expand All @@ -234,11 +235,11 @@ class Router {
? route.handler.bind(options.scope)
: route.handler;

const handlerMiddleware: Middleware = async (params, options, next) => {
const handlerResult = await handler(params, options);
options.res = handlerResultToWebResponse(
const handlerMiddleware: Middleware = async (params, reqCtx, next) => {
const handlerResult = await handler(params, reqCtx);
reqCtx.res = handlerResultToWebResponse(
handlerResult,
options.res.headers
reqCtx.res.headers
);

await next();
Expand All @@ -252,18 +253,18 @@ class Router {

const middlewareResult = await middleware(
route.params,
handlerOptions,
requestContext,
() => Promise.resolve()
);

// middleware result takes precedence to allow short-circuiting
const result = middlewareResult ?? handlerOptions.res;
const result = middlewareResult ?? requestContext.res;

return handlerResultToProxyResult(result);
} catch (error) {
this.logger.debug(`There was an error processing the request: ${error}`);
const result = await this.handleError(error as Error, {
...handlerOptions,
...requestContext,
scope: options?.scope,
});
return await webResponseToProxyResult(result);
Expand All @@ -284,7 +285,7 @@ class Router {
* back to a default handler.
*
* @param error - The error to handle
* @param options - Optional resolve options for scope binding
* @param options - Error resolve options including request context and scope
* @returns A Response object with appropriate status code and error details
*/
protected async handleError(
Expand All @@ -294,11 +295,8 @@ class Router {
const handler = this.errorHandlerRegistry.resolve(error);
if (handler !== null) {
try {
const { scope, ...handlerOptions } = options;
const body = await handler.apply(scope ?? this, [
error,
handlerOptions,
]);
const { scope, ...reqCtx } = options;
const body = await handler.apply(scope ?? this, [error, reqCtx]);
return new Response(JSON.stringify(body), {
status: body.statusCode,
headers: { 'Content-Type': 'application/json' },
Expand Down
4 changes: 2 additions & 2 deletions packages/event-handler/src/rest/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export const isAPIGatewayProxyResult = (
export const composeMiddleware = (middleware: Middleware[]): Middleware => {
return async (
params: Record<string, string>,
options: RequestContext,
reqCtx: RequestContext,
next: () => Promise<HandlerResponse | void>
): Promise<HandlerResponse | void> => {
let index = -1;
Expand All @@ -172,7 +172,7 @@ export const composeMiddleware = (middleware: Middleware[]): Middleware => {
}

const middlewareFn = middleware[i];
const middlewareResult = await middlewareFn(params, options, () =>
const middlewareResult = await middlewareFn(params, reqCtx, () =>
dispatch(i + 1)
);

Expand Down
6 changes: 3 additions & 3 deletions packages/event-handler/src/types/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type ErrorResolveOptions = RequestContext & ResolveOptions;

type ErrorHandler<T extends Error = Error> = (
error: T,
options: RequestContext
reqCtx: RequestContext
) => Promise<ErrorResponse>;

interface ErrorConstructor<T extends Error = Error> {
Expand Down Expand Up @@ -59,7 +59,7 @@ type HandlerResponse = Response | JSONObject;
type RouteHandler<
TParams = Record<string, unknown>,
TReturn = HandlerResponse,
> = (args: TParams, options: RequestContext) => Promise<TReturn>;
> = (args: TParams, reqCtx: RequestContext) => Promise<TReturn>;

type HttpMethod = keyof typeof HttpVerbs;

Expand All @@ -84,7 +84,7 @@ type NextFunction = () => Promise<HandlerResponse | void>;

type Middleware = (
params: Record<string, string>,
options: RequestContext,
reqCtx: RequestContext,
next: NextFunction
) => Promise<void | HandlerResponse>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {

const createErrorHandler =
(statusCode: HttpStatusCode, message?: string) =>
async (error: Error, _options: RequestContext) => ({
async (error: Error, _reqCtx: RequestContext) => ({
statusCode,
error: error.name,
message: message ?? error.message,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ describe('Class: Router - Basic Routing', () => {
const app = new Router();
const testEvent = createTestEvent('/test', 'GET');

app.get('/test', async (_params, options) => {
app.get('/test', async (_params, reqCtx) => {
return {
hasRequest: options.request instanceof Request,
hasEvent: options.event === testEvent,
hasContext: options.context === context,
hasRequest: reqCtx.request instanceof Request,
hasEvent: reqCtx.event === testEvent,
hasContext: reqCtx.context === context,
};
});

Expand Down
16 changes: 8 additions & 8 deletions packages/event-handler/tests/unit/rest/Router/decorators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,11 @@ describe('Class: Router - Decorators', () => {

class Lambda {
@app.get('/test')
public async getTest(_params: any, options: any) {
public async getTest(_params: any, reqCtx: any) {
return {
hasRequest: options.request instanceof Request,
hasEvent: options.event === testEvent,
hasContext: options.context === context,
hasRequest: reqCtx.request instanceof Request,
hasEvent: reqCtx.event === testEvent,
hasContext: reqCtx.context === context,
};
}

Expand Down Expand Up @@ -427,14 +427,14 @@ describe('Class: Router - Decorators', () => {

class Lambda {
@app.errorHandler(BadRequestError)
public async handleBadRequest(error: BadRequestError, options: any) {
public async handleBadRequest(error: BadRequestError, reqCtx: any) {
return {
statusCode: HttpErrorCodes.BAD_REQUEST,
error: 'Bad Request',
message: error.message,
hasRequest: options.request instanceof Request,
hasEvent: options.event === testEvent,
hasContext: options.context === context,
hasRequest: reqCtx.request instanceof Request,
hasEvent: reqCtx.event === testEvent,
hasContext: reqCtx.context === context,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,13 @@ describe('Class: Router - Error Handling', () => {
const app = new Router();
const testEvent = createTestEvent('/test', 'GET');

app.errorHandler(BadRequestError, async (error, options) => ({
app.errorHandler(BadRequestError, async (error, reqCtx) => ({
statusCode: HttpErrorCodes.BAD_REQUEST,
error: 'Bad Request',
message: error.message,
hasRequest: options.request instanceof Request,
hasEvent: options.event === testEvent,
hasContext: options.context === context,
hasRequest: reqCtx.request instanceof Request,
hasEvent: reqCtx.event === testEvent,
hasContext: reqCtx.context === context,
}));

app.get('/test', () => {
Expand Down
38 changes: 19 additions & 19 deletions packages/event-handler/tests/unit/rest/Router/middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ describe('Class: Router - Middleware', () => {
const app = new Router();
const executionOrder: string[] = [];

app.use(async (_params, _options, next) => {
app.use(async (_params, _reqCtx, next) => {
executionOrder.push('global-middleware');
await next();
});

const middleware: Middleware[] = middlewareNames.map(
(name) => async (_params, _options, next) => {
(name) => async (_params, _reqCtx, next) => {
executionOrder.push(name);
await next();
}
Expand Down Expand Up @@ -137,9 +137,9 @@ describe('Class: Router - Middleware', () => {
let middlewareParams: Record<string, string> | undefined;
let middlewareOptions: RequestContext | undefined;

app.use(async (params, options, next) => {
app.use(async (params, reqCtx, next) => {
middlewareParams = params;
middlewareOptions = options;
middlewareOptions = reqCtx;
await next();
});

Expand All @@ -161,7 +161,7 @@ describe('Class: Router - Middleware', () => {
vi.stubEnv('POWERTOOLS_DEV', 'true');
const app = new Router();

app.use(async (_params, _options, next) => {
app.use(async (_params, _reqCtx, next) => {
await next();
await next();
});
Expand Down Expand Up @@ -215,7 +215,7 @@ describe('Class: Router - Middleware', () => {
const app = new Router();
const executionOrder: string[] = [];

app.use(async (_params, _options, next) => {
app.use(async (_params, _reqCtx, next) => {
executionOrder.push('middleware1-start');
await next();
executionOrder.push('middleware1-end');
Expand Down Expand Up @@ -336,10 +336,10 @@ describe('Class: Router - Middleware', () => {
// Prepare
const app = new Router();

app.use(async (_params, options, next) => {
app.use(async (_params, reqCtx, next) => {
await next();
options.res.headers.set('x-custom-header', 'middleware-value');
options.res.headers.set('x-request-id', '12345');
reqCtx.res.headers.set('x-custom-header', 'middleware-value');
reqCtx.res.headers.set('x-request-id', '12345');
});

app.get('/test', async () => ({ success: true }));
Expand Down Expand Up @@ -367,10 +367,10 @@ describe('Class: Router - Middleware', () => {
// Prepare
const app = new Router();

app.use(async (_params, options, next) => {
app.use(async (_params, reqCtx, next) => {
await next();
const originalBody = await options.res.text();
options.res = new Response(`Modified: ${originalBody}`, {
const originalBody = await reqCtx.res.text();
reqCtx.res = new Response(`Modified: ${originalBody}`, {
headers: { 'content-type': 'text/plain' },
});
});
Expand All @@ -396,8 +396,8 @@ describe('Class: Router - Middleware', () => {
// Prepare
const app = new Router();

app.use(async (_params, options, next) => {
options.res.headers.set('x-before-handler', 'middleware-value');
app.use(async (_params, reqCtx, next) => {
reqCtx.res.headers.set('x-before-handler', 'middleware-value');
await next();
});

Expand Down Expand Up @@ -425,14 +425,14 @@ describe('Class: Router - Middleware', () => {
// Prepare
const app = new Router();

app.use(async (_params, options, next) => {
options.res.headers.set('x-test-header', 'before-next');
app.use(async (_params, reqCtx, next) => {
reqCtx.res.headers.set('x-test-header', 'before-next');
await next();
});

app.use(async (_params, options, next) => {
app.use(async (_params, reqCtx, next) => {
await next();
options.res.headers.set('x-test-header', 'after-next');
reqCtx.res.headers.set('x-test-header', 'after-next');
});

app.get('/test', async () => ({ success: true }));
Expand Down Expand Up @@ -460,7 +460,7 @@ describe('Class: Router - Middleware', () => {
const app = new Router();
const executionOrder: string[] = [];

app.use(async (_params, _options, next) => {
app.use(async (_params, _reqCtx, next) => {
executionOrder.push('middleware-start');
await next();
executionOrder.push('middleware-end');
Expand Down
Loading