mdziob
mdziob

Reputation: 1166

How to send error data to server in Angular 4+ HttpInterceptor

I've implemented HttpInterceptor for catching request errors in my Angular 5 application. My goal is to send another REST POST request to the server, which saves error log. It looks like this:

@Injectable()
export class RestErrorHandler implements HttpInterceptor {

private readonly ERROR_LOGGER_PATH: string = '/logger/errorEntry';

constructor(private http: HttpClient, private restUtils: RestApiUtilsService) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch((errorReponse: HttpErrorResponse) => {
        return this.handleRestError(errorReponse, req, next);
    });
}

public handleRestError(error: HttpErrorResponse, req: HttpRequest<any>, next: HttpHandler): ErrorObservable {
    let errorMessage = this.prepareErrorMessage(error);
    let entry = this.prepareEntry(errorMessage);
    this.http.post(this.restUtils.getUrl(this.ERROR_LOGGER_PATH), JSON.stringify(entry), this.restUtils.jsonResponseRequestOptions()).subscribe();
    return Observable.throw(error);
}
}

export const ErrorInterceptorProvider = {
provide: HTTP_INTERCEPTORS,
useClass: RestErrorHandler,
multi: true,
};

Later on, I register ErrorInterceptorProvider as a provider in module.

During start of the application, error occurs:

Cannot instantiate cyclic dependency! HttpClient ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
Cannot instantiate cyclic dependency! HttpClient ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
at NgModuleProviderAnalyzer.parse (compiler.js:19542)
at NgModuleCompiler.compile (compiler.js:20131)
at JitCompiler._compileModule (compiler.js:34430)
at eval (compiler.js:34361)
at Object.then (compiler.js:474)
at JitCompiler._compileModuleAndComponents (compiler.js:34359)
at JitCompiler.compileModuleAsync (compiler.js:34253)
at CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:239)
at PlatformRef.bootstrapModule (core.js:5561)
at eval (main.ts:10)

If I create another @Injectable() service calling rest API through HttpClient, which I inject inside RestErrorHandler there is no error. Why is it?

Upvotes: 0

Views: 485

Answers (2)

mdziob
mdziob

Reputation: 1166

Here is my final working solution:

@Injectable()
export class RestErrorHandler implements HttpInterceptor {

private readonly ERROR_LOGGER_PATH: string = '/logger/errorEntry';

constructor(private injector: Injector, private restUtils: RestApiUtilsService) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).catch((errorReponse: HttpErrorResponse) => {
        return this.handleRestError(errorReponse, req, next);
    });
}

public handleRestError(error: HttpErrorResponse, req: HttpRequest<any>, next: HttpHandler): ErrorObservable {
    let errorMessage = this.prepareErrorMessage(error);
    let entry = this.prepareEntry(errorMessage);
    if (!this.http) this.http = this.injector.get(HttpClient);
    this.http.post(this.restUtils.getUrl(this.ERROR_LOGGER_PATH), JSON.stringify(entry), this.restUtils.jsonResponseRequestOptions()).subscribe();
    return Observable.throw(error);
}
}

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691635

Just wait for the next angular release, or apply the workaround described in the commit fixing this issue:

Currently this is only possible by injecting the Injector and using it to resolve HttpClient at request time.

Upvotes: 1

Related Questions