在Angular 2+中压缩传出请求 [英] Compress Outgoing Requests in Angular 2+

查看:157
本文介绍了在Angular 2+中压缩传出请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对从Angular 4应用程序向API项目发送的POST和PUT JSON请求使用gzip或deflate压缩.

I want to use gzip or deflate compression on outgoing POST and PUT JSON requests to an API project from an Angular 4 application.

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

Presently, I'm using HttpClient to send the requests. I've tried using pako or zlib to generate the compressed content, but the server returns back responses indicating a bad implementation of the compression algorithm.

我的POST TypeScript如下所示:

My POST TypeScript looks like the following:

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

我尝试了各种缩小和压缩内容的排列,但是似乎没有任何效果.我还检查了Fiddler中的传出请求,并验证了Fiddler无法解释请求JSON.

I've tried various permutations of deflating and gzipping the content, but nothing seems to work. I've also inspected the outgoing requests in Fiddler and verified that Fiddler could not interpret the request JSON.

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

I've also verified that content is being sent with Content-Type: application/json; charset=UTF-8 and Content-Encoding: deflate with appropriate Accept-Encoding values.

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

At this point I'm sure I'm either doing something wrong I haven't figured out, or that I'm trying to do more than what HttpClient will allow me to do.

推荐答案

我自己已经开始工作了.

I've just gotten this working myself.

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

I think the problem may be the way you are using pako.

pako.gzip(obj)不会返回字符串,除非您显式传递该选项.它返回一个字节数组. (具体是Uint8Array)

pako.gzip(obj) does not return a string, unless you explicitly pass that option. It returns a byte array. (Uint8Array, specifically)

默认的HttpClient会尝试将其转换为json字符串,这是错误的.我做了以下事情:

The default HttpClient will try to turn this into a json string, which is wrong. I did the following:

  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.默认情况下通常不会处理此问题.
  1. The Content-Type and Content-Encoding headers need to be set correctly for a zipped byte array.
  2. the use of the .buffer property on the compressedBody object. HttpClient needs it this way so that it knows it is dealing with a byte array.
  3. Your API will need to be smart enough to convert the byte array to json on the other end. This usually isn't handled by default.

这篇关于在Angular 2+中压缩传出请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆