Sie sind auf Seite 1von 10

If you want to add authentication to your Ionic app, chances are high today

that you want to send some specific headers with all of your requests. And
although you could use another package inside your app, you can also
easily add your own HTTP interceptor for this!

In this Quick Win we will add a custom HTTP interceptor which will
intercept all outgoing HTTP calls that our Ionic app makes. Inside those
requests we will use a token that we store and retrieve from the Ionic
Storage and also catch any errors that happens at the top most level inside
the app.

The result looks like the gif above if you inspect your HTTP calls and
headers, so let’s dive into it!
Starting our HTTP Interceptor Ionic
App
We don’t need any special packages for this but just a blank Ionic app and
an additional provider, so go ahead and run:

Start our Interceptor app

1 ionic start interceptMe blank

2 cd ionic start interceptMe blank

3 ionic g provider interceptor

After this your provider will be automatically added to your module, but we
need to change it a bit. We want to provide it for
the HTTP_INTERCEPTORS so it looks just like the custom Ionic Error
handler. Also, we add
the HttpClientModule and IonicStorageModule to prepare
everything.
Go ahead and change yourapp/app.module.ts to:
Provide the Interceptor inside your ngModule

1 import { BrowserModule } from '@angular/platform-browser';

2 import { ErrorHandler, NgModule } from '@angular/core';

3 import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';

4 import { SplashScreen } from '@ionic-native/splash-screen';

5 import { StatusBar } from '@ionic-native/status-bar';

7 import { MyApp } from './app.component';


8 import { HomePage } from '../pages/home/home';

9 import { InterceptorProvider } from '../providers/interceptor/interceptor';

10

11 import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';

12 import { IonicStorageModule } from '@ionic/storage';

13

14 @NgModule({

15 declarations: [

16 MyApp,

17 HomePage

18 ],

19 imports: [

20 BrowserModule,

21 IonicModule.forRoot(MyApp),

22 IonicStorageModule.forRoot(),

23 HttpClientModule

24 ],

25 bootstrap: [IonicApp],

26 entryComponents: [

27 MyApp,

28 HomePage

29 ],

30 providers: [

31 StatusBar,

32 SplashScreen,

33 { provide: ErrorHandler, useClass: IonicErrorHandler },

34 { provide: HTTP_INTERCEPTORS, useClass: InterceptorProvider, multi: true },

35 ]

36 })

37 export class AppModule {}


That’s it for the setup, now the Interceptor will be used whenever an HTTP
call takes place and we just have to take care of adding the right headers
on the fly!

The HTTP Interceptor Provider


The heart of this Quick Win is the actual Http interceptor which only needs
to implement the intercept() function.
Inside the function we have to go through a few steps one by one and
especially take care of what we return so don’t confuse Promise and
Observables in here and don’t mess up with the async chain! You can find
more on this also in the video linked below.

For now, the steps are:

1. Get the stored token from Ionic Storage


2. Use the token inside addToken()
3. Change the headers of the request if the token exists
inside addToken(), otherwise return the request again
4. Handle the cloned request like a regular HTTP call
5. Catch errors that might come up and show an alert

Especially the last point is optional, I just wanted to show how you could
plug in some error mechanism at that place.

Now open your providers/interceptor/interceptor.ts and change it to:


The HTTP Interceptor

1 import { AlertController } from 'ionic-angular';

2 import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';


3 import { Injectable } from '@angular/core';

4 import { Storage } from '@ionic/storage';

6 import { Observable } from 'rxjs';

7 import { _throw } from 'rxjs/observable/throw';

8 import { catchError, mergeMap } from 'rxjs/operators';

10 @Injectable()

11 export class InterceptorProvider implements HttpInterceptor {

12

13 constructor(private storage: Storage, private alertCtrl: AlertController) { }

14

15 // Intercepts all HTTP requests!

16 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

17

18 let promise = this.storage.get('my_token');

19

20 return Observable.fromPromise(promise)

21 .mergeMap(token => {

22 let clonedReq = this.addToken(request, token);

23 return next.handle(clonedReq).pipe(

24 catchError(error => {

25 // Perhaps display an error for specific status codes here already?

26 let msg = error.message;

27

28 let alert = this.alertCtrl.create({

29 title: error.name,

30 message: msg,

31 buttons: ['OK']

32 });
33 alert.present();

34

35 // Pass the error to the caller of the function

36 return _throw(error);

37 })

38 );

39 });

40 }

41

42 // Adds the token to your headers if it exists

43 private addToken(request: HttpRequest<any>, token: any) {

44 if (token) {

45 let clone: HttpRequest<any>;

46 clone = request.clone({

47 setHeaders: {

48 Accept: `application/json`,

49 'Content-Type': `application/json`,

50 Authorization: `Bearer ${token}`

51 }

52 });

53 return clone;

54 }

55

56 return request;

57 }

58 }

Now we only need to add a simple test and we are done.

Making HTTP Requests


We should test regular requests and authenticated requests. We don#t
really have any authentication in place here, but it would work more or less
like the flow inside our app. Plus you would store some information from
the token or user so you don’t have to retrieve it all the time.
Anyway, we just switch our auth state around with a function and either
write to the storage or remove the key from the storage. That’s all we need
to do as the interceptor will handle the rest!

To test successful or failed requests we can also add 2 more functions, but
nothing of ths should be new to you so open
your pages/home/home.ts and change it to:
A dummy class for some HTTP calls

1 import { HttpClient } from '@angular/common/http';

2 import { Storage } from '@ionic/storage';

3 import { Component } from '@angular/core';

5 @Component({

6 selector: 'page-home',

7 templateUrl: 'home.html'

8 })

9 export class HomePage {

10

11 authenticated = false;

12 message = '';

13

14 constructor(private http: HttpClient, private storage: Storage) { }

15

16 setAuthState(authenticated) {
17 if(authenticated) {

18 this.storage.set('my_token', 'myspecialheadertoken').then(() => {

19 this.authenticated = true;

20 });

21 } else {

22 this.storage.remove('my_token').then(() => {

23 this.authenticated = false;

24 });

25 }

26 }

27

28 getSuccessful() {

29 this.http.get('https://pokeapi.co/api/v2/pokemon/').subscribe(res => {

30 this.message = res['results'][0].name;

31 });

32 }

33

34 getFail() {

35 this.http.get('https://notvalid.xy').subscribe(

36 res => {}

37 ,err => {

38 this.message = err.message;

39 }

40 );

41 }

42 }

The final piece is to wire up some buttons, but the following code doesn’t
really needs any explanation at all besides that it goes into
your pages/home/home.html:
The view to test our functionality
1 <ion-header>

2 <ion-navbar color="primary">

3 <ion-title>

4 Ionic HTTP Intercept

5 </ion-title>

6 </ion-navbar>

7 </ion-header>

9 <ion-content padding>

10

11 <ion-card text-center>

12 <ion-card-header>

13 My Auth State: {{ authenticated }}

14 </ion-card-header>

15 <ion-card-content>

16 {{ message }}

17 </ion-card-content>

18 </ion-card>

19

20 <button ion-button full (click)="setAuthState(true)" *ngIf="!authenticated">Login</button>

21 <button ion-button full color="danger" (click)="setAuthState(false)" *ngIf="authenticated">Logout</button>

22 <button ion-button full color="secondary" (click)="getSuccessful()">Get URL successful</button>

23 <button ion-button full color="light" (click)="getFail()">Get URL with error</button>

24

25 </ion-content>
Now you can make your authorised requests which will get the header
token added and the regular requests will not plus in case of an error you
directly see the alert that something went wrong with your request!

It’s actually not that hard to build your own logic for adding those kind of
things, but in a real environment you might need to make
the access/refresh token dance if a request fails or in the beginning of
your app check if a stored token is still valid.
You can also find a video version of this Quick Win below.

Das könnte Ihnen auch gefallen