压缩HTTP请求正文

目录

当我们在 Web 服务器上启动 gzip 压缩后,会极大提高加载网页的速度。同样,将 gzip 用于发送HTTP请求,也可以加快请求的响应速度。

gzip库

Python内置标准库 gzip,像 GNU 程序 gzip 和 gunzip 一样提供文件压缩和解压缩功能。Python 2 和 Python 3 的使用方法略有不同。

Python 2

需要使用 StringIO 模块的 StringIO 类,创建 StringIO 对象当做一个文件,传给 gzip 的 GzipFile 对象,GzipFile 会将字符串压缩后写入 StringIO 对象。使用 getvalue 方法从 StringIO 中获取压缩后的字符串。

s = StringIO.StringIO()
g = gzip.GzipFile(fileobj=s, mode='w')
g.write(post_data)
g.close()
gzipped_data = s.getvalue()

Python 3

Python 3 的 gzip 库提供更方面的 compress 和 decompress 函数,可以直接压缩/解压缩字符串(bytes)。

gzipped_data = gzip.compress(bytes(post_data), 'utf-8'))

解压缩

post_data = gzip.decompress(gzipped_data).decode('utf-8'))

使用Requests发送压缩的请求

发送经 gzip 压缩过的 HTTP 请求时,需要将 HTTP 头属性 content-encoding 设为 gzip。使用 Requests 可以用下面的方式发送请求:

response = requests.post(url, data=gzipped_data, headers={
    'content-encoding': 'gzip'
})

使用Flask接收压缩的请求

接收经 gzip 压缩过的 HTTP 请求时,需要使用 gzip 对数据解压。在 Flask 中需要检测请求 request 的 headers 属性中的 content-encoding 属性是否为 gzip。如果是,则需要调用 gzip 模块对请求数据 request.data 进行解压。

content_encoding = request.headers.get('content-encoding', '').lower()
if content_encoding == 'gzip':
    gzipped_data = request.data
    data_string = gzip.decompress(gzipped_data)
    body = json.loads(data_string.decode('utf-8'))
else:
    body = request.form

上面代码中接收的是压缩过的 json 字符串。

效率测试

下面是做得一个测试,向阿里云服务器发送HTTPS请求,同样的数据对比压缩前和压缩后的响应时间。
第一组

方式长度占用空间(B)时间(秒)
原始

2206325

2.2MB

2.592873

gzip

74111

75KB

0.162942

另一组

方式长度占用空间(B)时间(秒)
原始

631433

631KB

0.322468

gzip

34018

34KB

0.083316

从上面两组可以看到,使用 gzip 压缩数据可以大量减少整个请求的响应时间。相对于压缩解压缩所需要的额外时间,带宽才是更关键的制约因素,所以减少传输的数据量对提高速度至关重要。