[英]Angular 4.3 HttpClient : Intercept response
在Angular 4.3新版本中包含的新HttpClientModule
的文檔中,對攔截請求的機制進行了很好的解釋。 還提到了響應攔截器機制,但是我找不到任何關於它的信息。
有沒有人知道如何攔截響應以便在將正文消息發送到服務之前對其進行修改?
謝謝。
我最近制作了一個HttpInterceptor
,以便在客戶端解析某些 JSON 中的循環引用,實質上是將任何帶有$ref
屬性的對象替換為 JSON 中具有匹配$id
屬性的對象。 (這是在 Json.Net 配置了PreserveReferencesHandling.Objects
和ReferenceLoopHandling.Ignore
得到的輸出)。
這里的答案在某種程度上幫助了我,但沒有一個顯示如何修改響應的主體,就像 OP 需要的那樣。 為此,需要克隆事件並更新主體,如下所示:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).map(event => {
if (event instanceof HttpResponse && shouldBeIntercepted(event)) {
event = event.clone({ body: resolveReferences(event.body) })
}
return event;
});
}
任何不應修改的事件都會簡單地傳遞給下一個處理程序。
我想你可以像@federico-scamuzzi 建議的那樣使用do
,或者你可以像這樣使用map
和catch
:
import { Injectable } from '@angular/core';
import {
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpResponse
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.info('req.headers =', req.headers, ';');
return next.handle(req)
.map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse && ~~(event.status / 100) > 3) {
console.info('HttpResponse::event =', event, ';');
} else console.info('event =', event, ';');
return event;
})
.catch((err: any, caught) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 403) {
console.info('err.error =', err.error, ';');
}
return Observable.throw(err);
}
});
}
}
編輯:@LalitKushwah 詢問重定向if(!loggedIn)
。 我使用Route Guards ,特別是:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot
} from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../../api/auth/auth.service';
import { AlertsService } from '../alerts/alerts.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router,
private alertsService: AlertsService) {}
canActivate(next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
if (AuthService.loggedIn()) return true;
const url: string = state.url;
this.alertsService.add(`Auth required to view ${url}`);
this.router
.navigate(['/auth'], { queryParams: { redirectUrl: url } })
.then(() => {});
return false;
}
}
然后我可以簡單地將它作為參數添加到我的路線中:
{
path: 'dashboard', loadChildren:'app/dashboard/dashboard.module#DashboardModule',
canActivate: [AuthGuard]
}
自 Angular 6 發布以來,RxJs 6.0 更改了其接口,因此您不能以相同的方式使用運算符(例如.map()
、 .tap()
...)。
因此,上述大多數解決方案都已過時。
這是使用 RxJs 6.0+(使用pipe
)正確修改 Observable 內容的方法:
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';
@Injectable()
export class ResponseInterceptor implements HttpInterceptor {
intercept(req: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
event = event.clone({body: this.modifyBody(event.body)});
}
return event;
}));
}
private modifyBody(body: any) {
/*
* write your logic to modify the body
* */
}
}
據我所知(我只完成了請求的攔截並注入了身份驗證令牌)..你可以附加一個 .do() 並測試是否是一個響應..就像(如文檔所說):
import 'rxjs/add/operator/do';
export class TimingInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const started = Date.now();
return next
.handle(req)
.do(event => {
if (event instanceof HttpResponse) { //<-- HERE
const elapsed = Date.now() - started;
console.log(event} ms.`);
}
});
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.