Skip to content

Commit

Permalink
feat: added an interceptor for HTTP requests
Browse files Browse the repository at this point in the history
  • Loading branch information
rorteg committed Aug 31, 2021
1 parent 3e3de31 commit 2a04467
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 12 deletions.
35 changes: 35 additions & 0 deletions lib/feature-toggle-header-request.interceptor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Test, TestingModule } from '@nestjs/testing';
import { FeatureToggleHeaderRequestInterceptor } from './feature-toggle-header-request.interceptor';
import { FEATURE_TOGGLE_MODULE_OPTIONS } from './feature-toggle.constants';
import { FeatureToggleService } from './feature-toggle.service';

describe('FeatureToggleHeaderRequestInterceptor', () => {
let app: TestingModule;
let featureToggleHeaderRequestInterceptor: FeatureToggleHeaderRequestInterceptor;
beforeAll(async () => {
app = await Test.createTestingModule({
providers: [
{
provide: FeatureToggleService,
useClass: FeatureToggleService
},
{
provide: FeatureToggleHeaderRequestInterceptor,
useClass: FeatureToggleHeaderRequestInterceptor
},
{
provide: FEATURE_TOGGLE_MODULE_OPTIONS,
useValue: {}
}
]
}).compile();

featureToggleHeaderRequestInterceptor =
app.get<FeatureToggleHeaderRequestInterceptor>(
FeatureToggleHeaderRequestInterceptor
);
});
it('should be defined', () => {
expect(featureToggleHeaderRequestInterceptor).toBeDefined();
});
});
41 changes: 41 additions & 0 deletions lib/feature-toggle-header-request.interceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { FeatureToggleService } from './feature-toggle.service';
import { FeatureEntity } from './entities';

@Injectable()
export class FeatureToggleHeaderRequestInterceptor implements NestInterceptor {
constructor(private featureToggleService: FeatureToggleService) {}
async intercept(
context: ExecutionContext,
next: CallHandler
): Promise<Observable<any>> {
const headers = context.switchToHttp().getRequest().headers;
Object.keys(headers)
.filter((key) =>
key.includes(
this.featureToggleService.getHttpContextConfig()
?.keywordToBeSearchedInHeader ?? 'feature_'
)
)
.forEach(async (key) => {
const feature = (await this.featureToggleService.getFeature(
key.toUpperCase()
)) as FeatureEntity;

if (
typeof feature !== 'undefined' &&
feature.isAcceptHTTPRequestContext()
) {
feature.setValue(!!parseInt(headers[key] as string));
}
});

return next.handle();
}
}
31 changes: 21 additions & 10 deletions lib/feature-toggle.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,37 @@ import { FeatureToggleService } from './feature-toggle.service';
import { createFeatureToggleProvider } from './feature-toggle.providers';
import { FEATURE_TOGGLE_MODULE_OPTIONS } from './feature-toggle.constants';
import { FeatureToggleExpressMiddleware } from '.';
import { FeatureToggleHeaderRequestInterceptor } from './feature-toggle-header-request.interceptor';

@Module({
providers: [FeatureToggleService, {
provide: FeatureToggleExpressMiddleware,
useFactory: (FeatureToggleService: FeatureToggleService) => {
return new FeatureToggleExpressMiddleware(FeatureToggleService);
providers: [
FeatureToggleService,
{
provide: FeatureToggleExpressMiddleware,
useFactory: (FeatureToggleService: FeatureToggleService) => {
return new FeatureToggleExpressMiddleware(FeatureToggleService);
},
inject: [FeatureToggleService]
},
inject: [FeatureToggleService]
}],
exports:[FeatureToggleService]
{
provide: 'APP_INTERCEPTOR',
scope: Scope.REQUEST,
useClass: FeatureToggleHeaderRequestInterceptor
}
],
exports: [FeatureToggleService]
})
export class FeatureToggleModule {
static register(options: FeatureToggleModuleOptions): DynamicModule {
return {
module: FeatureToggleModule,
providers: createFeatureToggleProvider(options)
}
};
}

static registerAsync(options: FeatureToggleModuleAsyncOptions): DynamicModule {
static registerAsync(
options: FeatureToggleModuleAsyncOptions
): DynamicModule {
return {
module: FeatureToggleModule,
imports: options.imports || [],
Expand Down Expand Up @@ -78,4 +89,4 @@ export class FeatureToggleModule {
scope: Scope.REQUEST
};
}
}
}
2 changes: 1 addition & 1 deletion package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@commitlint/config-angular": "13.1.0",
"@nestjs/common": "8.0.6",
"@nestjs/core": "8.0.6",
"@nestjs/testing": "8.0.6",
"@nestjs/testing": "^8.0.6",
"@types/jest": "26.0.24",
"@types/node": "14.17.12",
"@typescript-eslint/eslint-plugin": "4.29.3",
Expand Down

0 comments on commit 2a04467

Please sign in to comment.