Skip to content

Commit 8913854

Browse files
sdangoldreamorosi
andauthored
feat(event-handler): implemented route prefixes in HTTP event handler (#4523)
Co-authored-by: Andrea Amorosi <dreamorosi@gmail.com>
1 parent b0b43e8 commit 8913854

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

packages/event-handler/src/rest/Router.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ class Router {
5656
* Whether the router is running in development mode.
5757
*/
5858
protected readonly isDev: boolean = false;
59+
/**
60+
* The base prefix to be used for all routes registered using this Router.
61+
*/
62+
protected readonly prefix?: Path;
5963

6064
public constructor(options?: RestRouterOptions) {
6165
this.context = {};
@@ -73,6 +77,7 @@ class Router {
7377
logger: this.logger,
7478
});
7579
this.isDev = isDevMode();
80+
this.prefix = options?.prefix;
7681
}
7782

7883
/**
@@ -238,9 +243,9 @@ class Router {
238243
);
239244
} else {
240245
const handler =
241-
options?.scope != null
242-
? route.handler.bind(options.scope)
243-
: route.handler;
246+
options?.scope == null
247+
? route.handler
248+
: route.handler.bind(options.scope);
244249

245250
const handlerResult = await handler(params, reqCtx);
246251
reqCtx.res = handlerResultToWebResponse(
@@ -281,9 +286,15 @@ class Router {
281286
public route(handler: RouteHandler, options: RestRouteOptions): void {
282287
const { method, path, middleware = [] } = options;
283288
const methods = Array.isArray(method) ? method : [method];
289+
let resolvedPath = path;
290+
if (this.prefix) {
291+
resolvedPath = path === '/' ? this.prefix : `${this.prefix}${path}`;
292+
}
284293

285294
for (const method of methods) {
286-
this.routeRegistry.register(new Route(method, path, handler, middleware));
295+
this.routeRegistry.register(
296+
new Route(method, resolvedPath, handler, middleware)
297+
);
287298
}
288299
}
289300

packages/event-handler/src/types/rest.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ type RestRouterOptions = {
4343
* When no logger is provided, we'll only log warnings and errors using the global `console` object.
4444
*/
4545
logger?: GenericLogger;
46+
/**
47+
* The base prefix to be used for all routes registered using this Router.
48+
*/
49+
prefix?: Path;
4650
};
4751

4852
interface CompiledRoute {

packages/event-handler/tests/unit/rest/Router/basic-routing.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,31 @@ describe('Class: Router - Basic Routing', () => {
117117
InternalServerError
118118
);
119119
});
120+
121+
it('routes to the prefixed path when having a shared prefix defined', async () => {
122+
// Prepare
123+
const app = new Router({
124+
prefix: '/todos',
125+
});
126+
app.post('/', async () => {
127+
return { actualPath: '/todos' };
128+
});
129+
app.get('/:todoId', async ({ todoId }) => {
130+
return { actualPath: `/todos/${todoId}` };
131+
});
132+
133+
// Act
134+
const createResult = await app.resolve(
135+
createTestEvent('/todos', 'POST'),
136+
context
137+
);
138+
const getResult = await app.resolve(
139+
createTestEvent('/todos/1', 'GET'),
140+
context
141+
);
142+
143+
// Assess
144+
expect(JSON.parse(createResult.body).actualPath).toBe('/todos');
145+
expect(JSON.parse(getResult.body).actualPath).toBe('/todos/1');
146+
});
120147
});

0 commit comments

Comments
 (0)