Skip to content

Commit

Permalink
Merge d68e615 into 3593577
Browse files Browse the repository at this point in the history
  • Loading branch information
giovanni-bertoncelli committed Apr 16, 2024
2 parents 3593577 + d68e615 commit 760b597
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 42 deletions.
53 changes: 28 additions & 25 deletions src/lib/components/ng-http-loader.component.ts
Expand Up @@ -10,7 +10,7 @@
import { Component, Input, OnInit, Type } from '@angular/core';
import { merge, Observable, partition, timer } from 'rxjs';
import { debounce, distinctUntilChanged, switchMap, tap } from 'rxjs/operators';
import { PendingRequestsInterceptor } from '../services/pending-requests-interceptor.service';
import { InterceptorFilters, PendingRequestsInterceptor } from '../services/pending-requests-interceptor.service';
import { SpinnerVisibilityService } from '../services/spinner-visibility.service';
import { Spinkit } from '../spinkits';

Expand All @@ -30,9 +30,28 @@ export class NgHttpLoaderComponent implements OnInit {
@Input() debounceDelay = 0;
@Input() entryComponent!: Type<unknown> | null;
@Input() extraDuration = 0;
@Input() filteredHeaders: string[] = [];
@Input() filteredMethods: string[] = [];
@Input() filteredUrlPatterns: string[] = [];

get filteredHeaders(): string[] {
return this.pendingRequestsInterceptor.filteredHeaders;
}
@Input()
set filteredHeaders(hs: string[]) {
this.updateFilters('filteredHeaders', hs);
}
get filteredMethods(): string[] {
return this.pendingRequestsInterceptor.filteredMethods;
}
@Input()
set filteredMethods(ms: string[]) {
this.updateFilters('filteredMethods', ms);
}
get filteredUrlPatterns(): string[] {
return this.pendingRequestsInterceptor.filteredUrlPatterns.map(p => `${p}`);
}
@Input()
set filteredUrlPatterns(ps: string[]) {
this.updateFilters('filteredUrlPatterns', ps.map(p => new RegExp(p)))
}
@Input() minDuration = 0;
@Input() opacity = '.7';
@Input() backdropBackgroundColor = '#f1f1f1';
Expand All @@ -44,7 +63,6 @@ export class NgHttpLoaderComponent implements OnInit {
ngOnInit(): void {
this.initIsvisibleObservable();
this.nullifySpinnerIfEntryComponentIsDefined();
this.initFilters();
}

private initIsvisibleObservable(): void {
Expand All @@ -68,26 +86,11 @@ export class NgHttpLoaderComponent implements OnInit {
}
}

private initFilters(): void {
this.initFilteredUrlPatterns();
this.initFilteredMethods();
this.initFilteredHeaders();
}

private initFilteredUrlPatterns(): void {
if (!!this.filteredUrlPatterns.length) {
this.filteredUrlPatterns.forEach(e =>
this.pendingRequestsInterceptor.filteredUrlPatterns.push(new RegExp(e))
);
}
}

private initFilteredMethods(): void {
this.pendingRequestsInterceptor.filteredMethods = this.filteredMethods;
}

private initFilteredHeaders(): void {
this.pendingRequestsInterceptor.filteredHeaders = this.filteredHeaders;
private updateFilters<K extends keyof InterceptorFilters>(
filterName: K,
value: InterceptorFilters[K]
): void {
(this.pendingRequestsInterceptor as InterceptorFilters)[filterName] = value;
}

private updateExpirationDelay(showSpinner: boolean): void {
Expand Down
41 changes: 31 additions & 10 deletions src/lib/services/pending-requests-interceptor.service.ts
Expand Up @@ -9,19 +9,27 @@

import { HTTP_INTERCEPTORS, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { ExistingProvider, Injectable } from '@angular/core';
import { Observable, ReplaySubject } from 'rxjs';
import { BehaviorSubject, Observable, ReplaySubject } from 'rxjs';
import { finalize } from 'rxjs/operators';

export type InterceptorFilters = {
filteredUrlPatterns: RegExp[],
filteredMethods: string[],
filteredHeaders: string[]
}

@Injectable({
providedIn: 'root'
})
export class PendingRequestsInterceptor implements HttpInterceptor {

private _pendingRequests = 0;
private _pendingRequestsStatus$ = new ReplaySubject<boolean>(1);
private _filteredUrlPatterns: RegExp[] = [];
private _filteredMethods: string[] = [];
private _filteredHeaders: string[] = [];
private _filters$ = new BehaviorSubject<InterceptorFilters>({
filteredUrlPatterns: [],
filteredHeaders: [],
filteredMethods: []
})
private _forceByPass = false;

get pendingRequestsStatus$(): Observable<boolean> {
Expand All @@ -33,35 +41,48 @@ export class PendingRequestsInterceptor implements HttpInterceptor {
}

get filteredUrlPatterns(): RegExp[] {
return this._filteredUrlPatterns;
return this._filters$.value.filteredUrlPatterns;
}

set filteredUrlPatterns(regexes: RegExp[]) {
this._filters$.next({
...this._filters$.value,
filteredUrlPatterns: regexes
})
}

set filteredMethods(httpMethods: string[]) {
this._filteredMethods = httpMethods;
this._filters$.next({
...this._filters$.value,
filteredMethods: httpMethods
})
}

set filteredHeaders(value: string[]) {
this._filteredHeaders = value;
this._filters$.next({
...this._filters$.value,
filteredHeaders: value
})
}

set forceByPass(value: boolean) {
this._forceByPass = value;
}

private shouldBypassUrl(url: string): boolean {
return this._filteredUrlPatterns.some(e => {
return this._filters$.value.filteredUrlPatterns.some(e => {
return e.test(url);
});
}

private shouldBypassMethod(req: HttpRequest<unknown>): boolean {
return this._filteredMethods.some(e => {
return this._filters$.value.filteredMethods.some(e => {
return e.toUpperCase() === req.method.toUpperCase();
});
}

private shouldBypassHeader(req: HttpRequest<unknown>): boolean {
return this._filteredHeaders.some(e => {
return this._filters$.value.filteredHeaders.some(e => {
return req.headers.has(e);
});
}
Expand Down
14 changes: 7 additions & 7 deletions src/test/components/ng-http-loader.component.spec.ts
Expand Up @@ -143,7 +143,7 @@ describe('NgHttpLoaderComponent', () => {
}));

it('should not show the spinner if the request is filtered by url', fakeAsync(() => {
component.filteredUrlPatterns.push('fake');
component.filteredUrlPatterns = ['fake'];
component.ngOnInit();

http.get('/fake').subscribe();
Expand All @@ -153,7 +153,7 @@ describe('NgHttpLoaderComponent', () => {
}));

it('should not show the spinner if the request is filtered by HTTP method', fakeAsync(() => {
component.filteredMethods.push('get');
component.filteredMethods = ['get'];
fixture.detectChanges();

http.get('/fake').subscribe();
Expand All @@ -163,7 +163,7 @@ describe('NgHttpLoaderComponent', () => {
}));

it('should not show the spinner if the request is filtered by HTTP header', fakeAsync(() => {
component.filteredHeaders.push('header-to-filter');
component.filteredHeaders = ['header-to-filter'];
fixture.detectChanges();

http.get('/fake', {
Expand All @@ -178,7 +178,7 @@ describe('NgHttpLoaderComponent', () => {
}));

it('should take care of query strings in filteredUrlPatterns', fakeAsync(() => {
component.filteredUrlPatterns.push('bar');
component.filteredUrlPatterns = ['bar'];
component.ngOnInit();

http.get(
Expand All @@ -195,7 +195,7 @@ describe('NgHttpLoaderComponent', () => {
}));

it('should correctly filter by URL with several requests and one pattern', fakeAsync(() => {
component.filteredUrlPatterns.push('\\d');
component.filteredUrlPatterns = ['\\d'];
component.ngOnInit();

http.get('/12345').subscribe();
Expand All @@ -213,7 +213,7 @@ describe('NgHttpLoaderComponent', () => {
}));

it('should correctly filter by HTTP method with several requests', fakeAsync(() => {
component.filteredMethods.push('pOsT');
component.filteredMethods = ['pOsT'];
fixture.detectChanges();

http.post('/12345', null).subscribe();
Expand All @@ -231,7 +231,7 @@ describe('NgHttpLoaderComponent', () => {
}));

it('should correctly filter by HTTP header with several requests', fakeAsync(() => {
component.filteredHeaders.push('My-HeAdER');
component.filteredHeaders = ['My-HeAdER'];
fixture.detectChanges();

http.get('/12345', {
Expand Down

0 comments on commit 760b597

Please sign in to comment.