【问题标题】:How to inject an HTTP request before user's request is sent如何在发送用户请求之前注入 HTTP 请求
【发布时间】:2017-06-18 21:12:01
【问题描述】:

我正在学习 Angular,作为其中的一部分,我正在尝试了解如何实现我想到的用例。此时,我正在尝试测试服务器通信。即,RxJs 的 Observables。

我想到的用例是发送一个 POST 请求,该请求需要在服务器端接受 X-XSRF-TOKEN 标头。这是第一次发送 GET 请求时作为 cookie 发送回客户端的安全标头。换句话说,与服务器的任何对话都不能以 POST 请求开始。

我希望实现这一点的方式是包装 Angular 的 Http 类:

import {Http, RequestOptions, RequestOptionsArgs, Response} from '@angular/http';
import { Injectable} from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { CookieService } from 'angular2-cookie/services/cookies.service';

@Injectable()
export class RestClient {
  private static xsrfTokenCookie: string = 'XSRF-TOKEN';
  private static xsrfTokenHeader: string = 'X-XSRF-TOKEN';
  private static xsrfToken: string = null;

  constructor(private http: Http, private cookies: CookieService) {}

  get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.http.get(url, options);
  }

  post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
    if (!options) {
      options = new RequestOptions(new Headers());
    }
    if (!RestClient.xsrfToken) {
      RestClient.xsrfToken = this.cookies.get(RestClient.xsrfTokenCookie);
    }
    if (!RestClient.xsrfToken) {
      //TODO: Somehow construct an Observable object which once subscribed, it will make a GET request
      // then using the returned cookie, it will construct the actual POST request.
    }
  }
}

所以我的问题是,我怎样才能编写一个 POST 请求,它首先发送一个 GET 请求,等待它的响应,然后它会发送实际的 POST 请求。当然,post 方法的调用者会得到的返回的 Observable 属于 POST 请求,而不是 GET 请求。所以如果我写:

restClient.post('/', {}).subcribe(response => {
  //It's POST's response
})

【问题讨论】:

    标签: angular rxjs angular2-http


    【解决方案1】:

    使用mergeMap:

        post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
            if (!options) {
              options = new RequestOptions(new Headers());
            }
            if (!RestClient.xsrfToken) {
              RestClient.xsrfToken = this.cookies.get(RestClient.xsrfTokenCookie);
            }
            if (!RestClient.xsrfToken) {
              return this.getToken(...)
                     .mergeMap(token => this.postToServer(...));
            }
          }
        }
    

    在这种情况下,getToken 可以是一个 私有 方法,它返回一个带有令牌值的 Observable。这同样适用于postToServer,但返回类型为ObservableReponse。通过创建可连接的最小焦点方法,您可以将逻辑封装成片段,并通过将它们设为私有来隐藏实现细节。

    【讨论】:

    • 不会使用mergeMap 导致在最终返回的 Observable 流中包含令牌?如果是这样,那不是我喜欢的东西!
    • 不,mergeMap 基本上将一个 observable 转换为另一个。返回的 Observable 将来自 postToServer()。检查learnrxjs.io/operators/transformation/mergemap.html
    【解决方案2】:

    使用flatMap。如果您想在触发新请求时忽略之前的请求,可以使用 switchMap。

    return get(getUrl,....)
       .switchMap( response => restClient.post(url, response.token .... )
    

    这将返回 post call 的 Observable。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-14
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      • 2018-05-04
      • 2012-07-04
      相关资源
      最近更新 更多