【问题标题】:Compress Outgoing Requests in Angular 2+在 Angular 2+ 中压缩传出请求
【发布时间】:2019-01-27 06:35:08
【问题描述】:

我想对从 Angular 4 应用程序到 API 项目的传出 POST 和 PUT JSON 请求使用 gzip 或 deflate 压缩。

目前,我正在使用 HttpClient 发送请求。我尝试使用 pako 或 zlib 来生成压缩内容,但服务器返回的响应表明压缩算法的实现不正确。

我的 POST TypeScript 如下所示:

public post(url: string, content: any): Observable < any > {
  const fullUrl: string = `${HttpService.baseUrl}/${url}`;

  Logger.debug(`Beginning HttpPost invoke to ${fullUrl}`, content);

  // Optionally, deflate the input
  const toSend: any = HttpService.compressInputIfNeeded(content);

  return Observable.create((obs: Observer < any > ) => {
    this.client.post(fullUrl, toSend, HttpService.getClientOptions()).subscribe(
      (r: any) => {
        Logger.debug(`HttpPost operation to ${fullUrl} completed`, r);

        // Send the response along to the invoker
        obs.next(r);
        obs.complete();
      },
      (err: any) => {
        Logger.error(`Error on HttpPost invoke to ${fullUrl}`, err);

        // Pass the error along to the client observer
        obs.error(err);
      }
    );
  });
}

private static getClientOptions(): {
  headers: HttpHeaders
} {
  return {
    headers: HttpService.getContentHeaders()
  };
}

private static getContentHeaders(): HttpHeaders {
  let headers: HttpHeaders = new HttpHeaders({
    'Content-Type': 'application/json; charset=utf-8'
  });

  // Headers are immutable, so any set operation needs to set our reference
  if (HttpService.deflate) {
    headers = headers.set('Content-Encoding', 'deflate');
  }
  if (HttpService.gzip) {
    headers = headers.set('Content-Encoding', 'gzip');
  }

  return headers;
}

private static compressInputIfNeeded(content: any): string {
  const json: string = JSON.stringify(content);

  Logger.debug('Pako Content', pako);

  if (HttpService.deflate) {
    const deflated: string = pako.deflate(json);
    Logger.debug(`Deflated content`, deflated);

    return deflated;
  }

  if (HttpService.gzip) {
    const zipped: string = pako.gzip(json);
    Logger.debug(`Zipped content`, zipped);

    return zipped;
  }

  return json;
}

我尝试了各种对内容进行放气和 gzip 压缩的排列,但似乎没有任何效果。我还检查了 Fiddler 中的传出请求,并确认 Fiddler 无法解释请求 JSON。

我还验证了使用 Content-Type: application/json; 发送内容charset=UTF-8 和 Content-Encoding:使用适当的 Accept-Encoding 值缩小。

在这一点上,我确定我做错了什么我还没有弄清楚,或者我正在尝试做的事情超出了 HttpClient 允许我做的事情。

【问题讨论】:

    标签: angular typescript compression gzip deflate


    【解决方案1】:

    我自己刚刚完成了这项工作。

    我认为问题可能出在您使用pako 的方式上。

    pako.gzip(obj) 不返回字符串,除非您明确传递该选项。它返回一个字节数组。 (Uint8Array,具体来说)

    默认的HttpClient会尝试把这个转成json字符串,这是错误的。我做了以下事情:

      const newHeaders: Headers = new Headers();
      newHeaders.append('Content-Encoding', 'gzip')
      newHeaders.set('Content-Type', 'application/octet-stream');
    
      var options = { headers: newHeaders, responseType: ResponseContentType.Json };
    
      var compressedBody = pako.gzip(JSON.stringify(body))
    
      client.post(url, compressedBody.buffer, options);
    

    注意几点:

    1. 需要为压缩字节数组正确设置 Content-TypeContent-Encoding 标头。
    2. compressedBody 对象上使用.buffer 属性。 HttpClient 需要这种方式,以便知道它正在处理一个字节数组。
    3. 您的 API 需要足够智能,才能在另一端将字节数组转换为 json。这通常不会默认处理。

    【讨论】:

      猜你喜欢
      • 2017-01-03
      • 1970-01-01
      • 2018-04-27
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 2011-07-01
      相关资源
      最近更新 更多