2017-08-08 226 views
19

有关包含在新版本Angular 4.3中的新的HttpClientModule的文档,他们很好地解释了拦截请求的机制,但也提到了响应拦截器机制,但他们从未说出任何有关它的内容。Angular 4.3 HttpClient:拦截响应

这里的任何人都有一个想法来拦截响应,并在发送到服务之前修改主体消息?

谢谢。

回答

2

从我能理解(我只是做了请求拦截并注入身份验证令牌)..你可以附上。做()和测试,如果是一个效应初探..像(如医生说):

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.`); 
     } 
     }); 
    } 

} 
28

我想你可以使用do为@费德里科 - scamuzzi建议,或者您可以使用mapcatch像这样:

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] 
} 
+3

你是我的英雄。希望有一天你会收到一个奥斯卡! –

+1

你能解释一下〜(event.status/100)> 3'吗? – sabithpocker

+0

如果它是一个400或500 HTTP错误,那么这种情况将是真实的。 '〜'处理str-> num转换 - 在这种情况下比'+'更好。 –

8

我最近做了一个HttpInterceptor为了解决在一些JSON循环引用客户端,基本上用具有匹配'$ id'属性的JSON中的对象替换具有'$ ref'属性的任何对象。 (这是您使用PreserveReferencesHandling.Objects和ReferenceLoopHandling.Ignore配置Json.Net时得到的输出。

这里的答案对我有些帮助,但没有一个显示如何修改响应的正文,就像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; 
    }); 
} 

不应该被修改简单地穿过下一个处理程序的任何事件。

+0

^^唯一的答案,实际上显示了如何修改响应,在Angular 5.2.4 typescript 2.6.2 –

+0

中为我工作我也在寻找这个,现在我意识到它与更改请求相同:'request = request.clone({url:'new-url'})'。很有用 – Guillaume