在Angular 2+中压缩传出请求 [英] Compress Outgoing Requests in 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);
请注意以下几点:
- 需要为压缩字节数组正确设置
Content-Type
和Content-Encoding
标头. - 在
compressedBody
对象上使用.buffer
属性.HttpClient
需要这种方式,以便它知道它正在处理字节数组. - 您的API必须足够聪明,才能将另一端的字节数组转换为json.默认情况下通常不会处理此问题.
- The
Content-Type
andContent-Encoding
headers need to be set correctly for a zipped byte array. - the use of the
.buffer
property on thecompressedBody
object.HttpClient
needs it this way so that it knows it is dealing with a byte array. - 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屋!