Skip to content

Commit

Permalink
fix(guard): Use the correct approach to check for excluded routes
Browse files Browse the repository at this point in the history
  • Loading branch information
kkoomen authored and jmcdo29 committed May 31, 2020
1 parent 7b8ab42 commit 38eac3c
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and routes.
## ThrottleGuard

Global guard. Check if metadata exists for guard. If not, check if route is in
`ignoreRoutes`. If so, return `true`. If not, apply defaults from package
`excludeRoutes`. If so, return `true`. If not, apply defaults from package
(configured via module). If metadata does exist, use metadata instead of
defaults (easy overriding) Pull throttlerStorage from `ThrottlerStorage` class
via `getRecord()` method. Will return a number, if number is gte max, return
Expand Down
30 changes: 17 additions & 13 deletions src/throttler.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class ThrottlerGuard implements CanActivate {
private readonly storageService: ThrottlerStorageService,
) {}

// TODO: Return true if current route is in ignoreRoutes.
// TODO: Return true if current route is in excludeRoutes.
async canActivate(context: ExecutionContext): Promise<boolean> {
const handler = context.getHandler();
const headerPrefix = 'X-RateLimit';
Expand All @@ -30,21 +30,25 @@ export class ThrottlerGuard implements CanActivate {
return true;
}

// Return early if the current route is ignored.
// Return early if the current route should be excluded.
const req = context.switchToHttp().getRequest();
const routes = this.normalizeRoutes(this.options.ignoreRoutes);
for (const route of routes) {
const currentRoutePath = req.url.replace(/^\/+/, '');
const currentRouteMethod = this.reflector.get<RequestMethod>('method', handler);
const routes = this.normalizeRoutes(this.options.excludeRoutes);
const originalUrl = req.originalUrl.replace(/^\/+/, '');
const reqMethod = req.method;
const queryParamsIndex = originalUrl && originalUrl.indexOf('?');
const pathname = queryParamsIndex >= 0
? originalUrl.slice(0, queryParamsIndex)
: originalUrl;

const ignored = (
route.path === currentRoutePath &&
[RequestMethod.ALL, currentRouteMethod].indexOf(route.method) !== -1
) || route.regex.exec(currentRoutePath);

if (ignored) return true;
}
const isExcluded = routes.some(({ method, regex }) => {
if (RequestMethod.ALL === method || RequestMethod[method] === reqMethod) {
return regex.exec(pathname);
}
return false;
});
if (isExcluded) return true;

// Here we start to check the amount of requests being done against the ttl.
const res = context.switchToHttp().getResponse();
const key = md5(`${req.ip}-${context.getClass().name}-${handler.name}`)
const record = this.storageService.getRecord(key);
Expand Down
2 changes: 1 addition & 1 deletion src/throttler.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Type } from './type';


export interface ThrottlerOptions {
ignoreRoutes?: Array<string | RouteInfo>;
excludeRoutes?: Array<string | RouteInfo>;
limit?: number;
ttl?: number;
storage?: Type<ThrottlerStorage>
Expand Down
10 changes: 5 additions & 5 deletions test/app/app.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,30 @@ export class AppController {
return 'test';
}

// Route that are defined in the `ignoreRoutes` property.
// Route that are defined in the `excludeRoutes` property.

// ignoreRoutes: ['ignored']
// excludeRoutes: ['ignored']
@Get('ignored')
@Throttle(2, 10)
async ignored() {
return 'ignored';
}

// ignoreRoutes: [{ path: 'ignored-2', method: RequestMethod.POST }]
// excludeRoutes: [{ path: 'ignored-2', method: RequestMethod.POST }]
@Post('ignored-2')
@Throttle(2, 10)
async ignored2() {
return 'ignored';
}

// ignoreRoutes: [{ path: 'ignored-3', method: RequestMethod.ALL }]
// excludeRoutes: [{ path: 'ignored-3', method: RequestMethod.ALL }]
@All('ignored-3')
@Throttle(2, 10)
async ignored3() {
return 'ignored';
}

// ignoreRoutes: [{ path: 'ignored/:foo', method: RequestMethod.GET }]
// excludeRoutes: [{ path: 'ignored/:foo', method: RequestMethod.GET }]
@Get('ignored/:foo')
@Throttle(2, 10)
async ignored4() {
Expand Down
2 changes: 1 addition & 1 deletion test/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AppService } from './app.service';

@Module({
imports: [ThrottlerModule.forRoot({
ignoreRoutes: [
excludeRoutes: [
'ignored',
{ path: 'ignored-2', method: RequestMethod.POST },
{ path: 'ignored-3', method: RequestMethod.ALL },
Expand Down

0 comments on commit 38eac3c

Please sign in to comment.