压缩传出请求 Angular 2+
Compress Outgoing Requests in Angular 2+
我想对来自 Angular 4 应用程序的传出 POST 和 PUT JSON 请求对 API 项目使用 gzip 或 deflate 压缩。
目前,我正在使用 HttpClient 发送请求。我试过使用 pako 或 zlib 生成压缩内容,但服务器 returns 返回响应表明压缩算法实施不当。
我的 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.
我还验证了正在发送的内容的内容类型:application/json; charset=UTF-8 和 Content-Encoding:使用适当的 Accept-Encoding 值进行压缩。
在这一点上,我确定我要么做错了我还没弄清楚的事情,要么我试图做的事情超出了 HttpClient 允许我做的事情。
我刚刚自己完成了这项工作。
我认为问题可能出在您使用 pako
的方式上。
pako.gzip(obj)
不是 return 字符串,除非您明确传递该选项。它 return 是一个字节数组。 (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);
注意几点:
- 需要为压缩字节数组正确设置
Content-Type
和 Content-Encoding
headers。
- 使用
.buffer
属性就compressedBody
object。 HttpClient
以这种方式需要它,以便它知道它正在处理一个字节数组。
- 您的 API 需要足够聪明才能将字节数组转换为另一端的 json。默认情况下通常不会处理此问题。
我想对来自 Angular 4 应用程序的传出 POST 和 PUT JSON 请求对 API 项目使用 gzip 或 deflate 压缩。
目前,我正在使用 HttpClient 发送请求。我试过使用 pako 或 zlib 生成压缩内容,但服务器 returns 返回响应表明压缩算法实施不当。
我的 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.
我还验证了正在发送的内容的内容类型:application/json; charset=UTF-8 和 Content-Encoding:使用适当的 Accept-Encoding 值进行压缩。
在这一点上,我确定我要么做错了我还没弄清楚的事情,要么我试图做的事情超出了 HttpClient 允许我做的事情。
我刚刚自己完成了这项工作。
我认为问题可能出在您使用 pako
的方式上。
pako.gzip(obj)
不是 return 字符串,除非您明确传递该选项。它 return 是一个字节数组。 (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);
注意几点:
- 需要为压缩字节数组正确设置
Content-Type
和Content-Encoding
headers。 - 使用
.buffer
属性就compressedBody
object。HttpClient
以这种方式需要它,以便它知道它正在处理一个字节数组。 - 您的 API 需要足够聪明才能将字节数组转换为另一端的 json。默认情况下通常不会处理此问题。