2

In Angular 1, globally handling an HTTP response status is done with $httpProvider:

angular.module('app', [])
    .service('httpResponseInterceptor', ['$q', function ($q) {
        this.response = function (response) {
            if (response.status === 418) {
                // do some stuff here
            }
            return response || $q.when(response);
        };
        this.responseError = function (response) {
            if (response.status === 418) {
                // do some stuff here
            }
            return $q.reject(response);
        };
    }])
    .config(['$httpProvider', function ($httpProvider) {
        // do routing, etc.

        $httpProvider.interceptors.push('httpResponseInterceptor');
    }]);


In Angular 2, it is done extending Http something like this instead:

import { Injectable } from '@angular/core';
import {
    Http,
    Response,
    Request,
    RequestOptions,
    RequestOptionsArgs,
    XHRBackend
} from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';

@Injectable()
export class HttpInterceptor extends Http {

  constructor(xhrBackend: XHRBackend, requestOptions: RequestOptions) {
    super(xhrBackend, requestOptions);
  }

  private catchErrors() {
    return (response: Response) => {
      if (response.status === 418) {
            // do some stuff here
      }
      return Observable.throw(response);
    };
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    return super.request(url, options)
          .catch(this.catchErrors());
  }
}

...and by including this in app.module.ts:

providers: [
    { provide: Http, useClass: HttpInterceptor }
]

See this stackoverflow answer and this gist for reference.


However, I am getting this error with the above Angular 2 code:

Cannot instantiate cyclic dependency! Http: in NgModule AppModule

1 Answer 1

4

This configuration worked for me; I'm using Angular 2 v2.4.1:

app.module.ts

{
    provide: Http,
    useFactory: (backend: XHRBackend, options: RequestOptions) => {
        return new HttpInterceptor(backend, options);
    },
    deps: [XHRBackend, RequestOptions]
}

HttpInterceptor.ts

import { Injectable } from '@angular/core';
import {
    Http,
    ConnectionBackend,
    RequestOptions,
    RequestOptionsArgs,
    Request,
    Response,
    Headers
} from '@angular/http';

import { Observable } from 'rxjs/Rx';

@Injectable()
export class HttpInterceptor extends Http {
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
        super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.request(url, options));
    }

   ...
}
Sign up to request clarification or add additional context in comments.

1 Comment

thank you for this! useFactory and deps is working correctly for me, instead of useClass.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.