Angular 4.3 HttpClient:拦截响应

oli*_*sin 53 javascript http interceptor angular

HttpClientModule新版Angular 4.3中包含的新文档中,很好地解释了拦截请求的机制.还提到了响应拦截器机制,但是我找不到任何关于它的信息.

有没有人知道如何拦截响应,以便在发送到服务之前修改正文消息?

谢谢.

A T*_*A T 45

我想你可以使用do@ federico-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);
        }
      });
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑:@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;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以简单地将其作为参数添加到我的路线中:

{
  path: 'dashboard', loadChildren:'app/dashboard/dashboard.module#DashboardModule',
  canActivate: [AuthGuard]
}
Run Code Online (Sandbox Code Playgroud)

  • 你是我的英雄.希望有一天你会收到奥斯卡! (3认同)
  • 你能解释一下`〜(event.status/100)> 3`吗? (2认同)
  • 由于 event.status 已经是数字,这还不够:if(event.status &gt;= 400)?感觉这更容易阅读并且做同样的事情。 (2认同)

sig*_*nlo 38

我最近做了一个HttpInterceptor以解决客户端的一些JSON中的循环引用,实质上用$ref具有匹配$id属性的JSON中的对象替换任何具有属性的对象.(如果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;
    });
}
Run Code Online (Sandbox Code Playgroud)

任何不应修改的事件都会简单地传递给下一个处理程序.

  • 如果您在2019年来到这里-管道还需要:从'rxjs / operators'导入{map};`next.handle(clonedRequest).pipe(map(event =&gt; {...}})) (8认同)
  • ^^实际上显示如何修改响应的唯一答案,在Angular 5.2.4 typescript 2.6.2中为我工作 (3认同)

ima*_*era 19

随着Angular 6的发布,他们已经改编了RxJs 6.0,因为大多数上述解决方案都无法在这个特定的角度版本中使用,这就是你如何正确修改Observable的内容



import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs/internal/Observable';
import {Injectable} from '@angular/core';
import {tap} from 'rxjs/operators';

@Injectable()
export class ResponseInterceptor implements HttpInterceptor {

    intercept(req: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {

        return next.handle(req).pipe(tap((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
        * */
    }
}


  • 这对我不起作用。使用`tap'不会保留我正在创建的实际修改后的主体。我将其更改为`map`,它代替了。 (4认同)

fed*_*zzi 5

根据我的理解(我只完成了对请求的拦截并注入了身份验证令牌)..你可以附加一个.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.`);
        }
      });
  }

}
Run Code Online (Sandbox Code Playgroud)