2017-08-08 236 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