Skip to content

Instantly share code, notes, and snippets.

@mrgoos
Last active September 17, 2024 21:54
Show Gist options
  • Save mrgoos/45ab013c2c044691b82d250a7df71e4c to your computer and use it in GitHub Desktop.
Save mrgoos/45ab013c2c044691b82d250a7df71e4c to your computer and use it in GitHub Desktop.
Intercepting http request/respons in Angular 2. Works from version 2.3.0.
...
...
providers: [
{ provide: Http, useClass: ExtendedHttpService }
]
...
...
import { Injectable } from '@angular/core';
import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';
import { AuthService } from './auth/auth.service';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class ExtendedHttpService extends Http {
constructor(backend: XHRBackend, defaultOptions: RequestOptions, private router: Router, private authService: AuthService) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
//do whatever
if (typeof url === 'string') {
if (!options) {
options = { headers: new Headers() };
}
this.setHeaders(options);
} else {
this.setHeaders(url);
}
return super.request(url, options).catch(this.catchErrors());
}
private catchErrors() {
return (res: Response) => {
if (res.status === 401 || res.status === 403) {
//handle authorization errors
//in this example I am navigating to logout route which brings the login screen
this.router.navigate(['logout']);
}
return Observable.throw(res);
};
}
private setHeaders(objectToSetHeadersTo: Request | RequestOptionsArgs) {
//add whatever header that you need to every request
//in this example I add header token by using authService that I've created
objectToSetHeadersTo.headers.set('Token', this.authService.getToken());
}
}
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
@Injectable()
export class MyService {
constructor(private http: Http) { } // the provided ExtendedHttpService will be injected here
getFromServer(): Observable<Whatever[]> {
return this.http.get(WHATEVER_URL).map((res: Response) => res.json());
}
}
@mosinski
Copy link

Hi, I'm trying to use this gist but I'm still getting error: Can not find name 'Router'
I made sure that I got import {Router} from '@ angular / router'
Maybe someone else got same errror ? 🤞

@jpsaints
Copy link

jpsaints commented Mar 10, 2017

Hi, I tried to use this gist and I'm getting an error saying: Unhandled Promise rejection: Provider parse errors:
Cannot instantiate cyclic dependency! Http

I'm getting this error when I'm using

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

@sirsimon
Copy link

So have I Unhandled Promise rejection: Provider parse errors: Cannot instantiate cyclic dependency! Http: in NgModule AppModule in ./AppModule ; Zone: <root> ; Task: Promise.then ; Value:

@danfri86
Copy link

I have the same as you @sirsimon.
My dependencies is ExtendedHttpService > AuthService > ExtendedHttpService. Did you find a solution?

@caroso1222
Copy link

caroso1222 commented Mar 28, 2017

It seems that Router cannot be injected in a service. Or at least I'm getting undefined for router when trying to navigate. Cannot find name 'Router'. Going back to window.location.href :(

@miczed
Copy link

miczed commented Mar 29, 2017

I ran into the same issue today. As soon as anything inside authService has Http as a dependency you get a cyclic dependency error. Did anybody come up with a solution to this?

@mvkirk
Copy link

mvkirk commented Mar 30, 2017

@miczed It's because in your @NgModule you import HttpModule which already incluse Http.
So in the provider, you must use a factory :

providers: [
...
{
      provide: Http,
      useFactory: (backend: XHRBackend, options: RequestOptions, tokenService: TokenService, router: Router) => {
        return new ExtendedHttpService(backend, options, authService, router);
      },
      deps: [XHRBackend, RequestOptions, AuthService, Router]
   }
]
...

@jarodsmk
Copy link

jarodsmk commented Mar 31, 2017

Just adding to the answer by @mvkirk :

Using @angular/core 2.4.8, this returns the following error:

ERROR in Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function (position XX:XX in the original .ts file), resolving symbol AppModule in ...XX/app.module.ts

To curb this, create a seperate file for the factory, as described here:
https://pub.scotch.io/@kashyapmukkamala/using-http-interceptor-with-angular2

@jonesmac
Copy link

jonesmac commented Apr 25, 2017

Has this been tested with the latest version of Angular? (4.0.3)
I cannot seem to navigate anywhere once inside the if block (L35).

nm...The issue seems to be L37. I'm using Angular 4.0.3 and if you return Observable.throw, navigation will not work, but using .of instead allows the navigation to continue. See my gist

@webmobiles
Copy link

I can't get 401 error from one of my cakephp server, just from a node server, why? on the browser have 401 error, but headers,response from angular give me status =0, i'm using jwt and angular 4.1

@ailic
Copy link

ailic commented Aug 13, 2017

This problem is very well explained on StackOverflow's question page. Personally, I'm do not like approach which is listed there as an accepted answer, but it's completely obvious that injector must be used on one way or another.

@duncanhoggan
Copy link

Just implemented this, works great nice and simple. Great platform to build your own logic off.

@dhurba87
Copy link

Good job man. You saved my lot of time.

@rajkumar-patidar
Copy link

How we can use same into angular 6?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment