Angular Interceptors - рабочий пример
Главной особенностью @angular/common/http
является interceptors, возможность объявлять перехватчики, которые находятся между вашим приложением и бэкэндом. Когда ваше приложение делает запрос, перехватчики преобразуют его перед отправкой на сервер (Удобно добавлять заголовки к запросом). Применяется для всего: от аутентификации до логирования.
Создание приложения
ng new interceptors
cd interceptors
ng g service api
Создадим сервис api.service.ts
, который будет получать данные с jsonplaceholder.typicode.com
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
export interface Posts {
userId: number;
id: number;
title: string;
body: string;
}
@Injectable()
export class ApiService {
private postsURL = 'https://jsonplaceholder.typicode.com/posts';
constructor(private http: HttpClient) { }
getData(): Observable {
return this.http
.get(this.postsURL);
}
}
В главный модуль app.module.ts
добавляем
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; // <- добавлено
...
imports: [
BrowserModule,
HttpClientModule // <- добавлено
],
...
HTML код app компонента
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
<img width="300" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<div class="container">
<div class="row">
<table class="table">
<thead class="thead-inverse">
<tr>
<th class="text-center">ID</th>
<th class="text-center">Title</th>
<th class="text-center">Body</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let post of posts">
<td>{{post.id}}</td>
<td class="text-center">{{post.title}}</td>
<td>{{post.body}}</td>
</tr>
</tbody>
</table>
</div>
</div>
Создание перехватчика
Чтобы реализовать перехватчик, нужно создать класс, реализующий интерфейс HttpInterceptor, который имеет один метод intercept()
. Он принимает два параметра (req, next) и возварщает Observable. По сути первый параметр входящий запрос, второй - исходящий. Поэтому нам необходимо вернуть запрос, делается через метод handle. Далее следует зарегистрировать класс перехватчика в приложении.
ng g class api.interceptor
Для начала создадим простой перехватчик, который ничего не делает, просто принимает и отправляет запрос, не изменяя его:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
@Injectable()
export class ParamInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req);
}
}
Теперь нужно зарегистрировать перехватчик. Сделаем это в app.module.ts
.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; // <- добавлено
import { AppComponent } from './app.component';
import { ApiService } from './api.service';
import { AuthInterceptor, ParamInterceptor } from './api.interceptor';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule // <- добавлено
],
providers: [
ApiService, {
provide: HTTP_INTERCEPTORS,
useClass: ParamInterceptor,
multi: true
}],
bootstrap: [AppComponent]
})
export class AppModule { }
Теперь все запросы в приложении обрабатываются перехватчиком ParamInterceptor. Добавим логики. Будем добавлять параметр UserId = 7, для запросов к серверу jsonplaceholder.typicode.com
.
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
@Injectable()
export class ParamInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.url.includes('jsonplaceholder.typicode.com')) {
const paramReq = req.clone({
params: req.params.set(
'userId',
'7'
)
});
return next.handle(paramReq);
} else {
return next.handle(req);
}
}
}
Функция clone
используется, потому что объект req является immutable (Неизменяемым).