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
19 changes: 15 additions & 4 deletions packages/event-handler/src/rest/Router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class Router {
* Whether the router is running in development mode.
*/
protected readonly isDev: boolean = false;
/**
* The base prefix to be used for all routes registered using this Router.
*/
protected readonly prefix?: Path;

public constructor(options?: RestRouterOptions) {
this.context = {};
Expand All @@ -73,6 +77,7 @@ class Router {
logger: this.logger,
});
this.isDev = isDevMode();
this.prefix = options?.prefix;
}

/**
Expand Down Expand Up @@ -238,9 +243,9 @@ class Router {
);
} else {
const handler =
options?.scope != null
? route.handler.bind(options.scope)
: route.handler;
options?.scope == null
? route.handler
: route.handler.bind(options.scope);

const handlerResult = await handler(params, reqCtx);
reqCtx.res = handlerResultToWebResponse(
Expand Down Expand Up @@ -281,9 +286,15 @@ class Router {
public route(handler: RouteHandler, options: RestRouteOptions): void {
const { method, path, middleware = [] } = options;
const methods = Array.isArray(method) ? method : [method];
let resolvedPath = path;
if (this.prefix) {
resolvedPath = path === '/' ? this.prefix : `${this.prefix}${path}`;
}

for (const method of methods) {
this.routeRegistry.register(new Route(method, path, handler, middleware));
this.routeRegistry.register(
new Route(method, resolvedPath, handler, middleware)
);
}
}

Expand Down
4 changes: 4 additions & 0 deletions packages/event-handler/src/types/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ type RestRouterOptions = {
* When no logger is provided, we'll only log warnings and errors using the global `console` object.
*/
logger?: GenericLogger;
/**
* The base prefix to be used for all routes registered using this Router.
*/
prefix?: Path;
};

interface CompiledRoute {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,31 @@ describe('Class: Router - Basic Routing', () => {
InternalServerError
);
});

it('routes to the prefixed path when having a shared prefix defined', async () => {
// Prepare
const app = new Router({
prefix: '/todos',
});
app.post('/', async () => {
return { actualPath: '/todos' };
});
app.get('/:todoId', async ({ todoId }) => {
return { actualPath: `/todos/${todoId}` };
});

// Act
const createResult = await app.resolve(
createTestEvent('/todos', 'POST'),
context
);
const getResult = await app.resolve(
createTestEvent('/todos/1', 'GET'),
context
);

// Assess
expect(JSON.parse(createResult.body).actualPath).toBe('/todos');
expect(JSON.parse(getResult.body).actualPath).toBe('/todos/1');
});
});