简体   繁体   English

Angular 4.3 HttpClient:拦截响应

[英]Angular 4.3 HttpClient : Intercept response

In the documentation about the new HttpClientModule included in the new version of Angular 4.3, the mechanism to intercept requests is explained very well.在Angular 4.3新版本中包含的新HttpClientModule的文档中,对拦截请求的机制进行了很​​好的解释。 There is also mention of the response interceptor mechanism however I cannot find anything about it.还提到了响应拦截器机制,但是我找不到任何关于它的信息。

Does anyone have an idea about how to intercept a response in order to modify the body message before it is sent to the service?有没有人知道如何拦截响应以便在将正文消息发送到服务之前对其进行修改?

Thanks.谢谢。

I recently made an HttpInterceptor in order to resolve cyclical references in some JSON on the client side, essentially replacing any object with a $ref property with the object in the JSON that has a matching $id property.我最近制作了一个HttpInterceptor ,以便在客户端解析某些 JSON 中的循环引用,实质上是将任何带有$ref属性的对象替换为 JSON 中具有匹配$id属性的对象。 (This is the output you get if Json.Net is configured with PreserveReferencesHandling.Objects and ReferenceLoopHandling.Ignore ). (这是在 Json.Net 配置了PreserveReferencesHandling.ObjectsReferenceLoopHandling.Ignore得到的输出)。

The answers here helped me some of way, but none of them show how to modify the body of the response, like the OP needs.这里的答案在某种程度上帮助了我,但没有一个显示如何修改响应的主体,就像 OP 需要的那样。 In order to do so, one needs to clone the event and update the body, like so:为此,需要克隆事件并更新主体,如下所示:

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

Any event that should not be modified is simply passed through to the next handler.任何不应修改的事件都会简单地传递给下一个处理程序。

I suppose you can use do as @federico-scamuzzi suggested, or you can use map and catch like so:我想你可以像@federico-scamuzzi 建议的那样使用do ,或者你可以像这样使用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);
        }
      });
  }
}

EDIT: @LalitKushwah was asking about redirecting if(!loggedIn) .编辑:@LalitKushwah 询问重定向if(!loggedIn) I use Route Guards , specifically:我使用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;
  }
}

Then I can simply add that as an argument to my route:然后我可以简单地将它作为参数添加到我的路线中:

{
  path: 'dashboard', loadChildren:'app/dashboard/dashboard.module#DashboardModule',
  canActivate: [AuthGuard]
}

Since Angular 6 release, RxJs 6.0 changed its interface, so you cannot use operators the same way (like .map() , .tap() ...).自 Angular 6 发布以来,RxJs 6.0 更改了其接口,因此您不能以相同的方式使用运算符(例如.map().tap() ...)。
Because of that, most of the above solutions are outdated.因此,上述大多数解决方案都已过时。
This is how you correctly modify content of an Observable using RxJs 6.0+ (with pipe ):这是使用 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
        * */
    }
}

From what i can understand (I've only done the intercept for request and inject auth token) .. you can attach a .do() and test if is a reponse .. like (as doc says):据我所知(我只完成了请求的拦截并注入了身份验证令牌)..你可以附加一个 .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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM