压缩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请求,同样的数据对比压缩前和压缩后的响应时间。
第一组

<td>
  长度
</td>

<td>
  <span lang="zh-CN">占用空间</span><span lang="en-US">(B)</span>
</td>

<td>
  时间(秒)
</td>
<td>
  <p lang="en-US">
    2206325
  </p>
</td>

<td>
  <p lang="en-US">
    2.2MB
  </p>
</td>

<td>
  <p lang="en-US">
    2.592873
  </p>
</td>
<td>
  <p lang="en-US">
    74111
  </p>
</td>

<td>
  75KB
</td>

<td>
  <p lang="en-US">
    0.162942
  </p>
</td>

另一组

  <td>
    长度
  </td>
  
  <td>
    <span lang="zh-CN">占用空间</span><span lang="en-US">(</span><span lang="en-US">B)</span>
  </td>
  
  <td>
    时间(秒)
  </td>
</tr>

<tr>
  <td>
    原始
  </td>
  
  <td>
    <p lang="en-US">
      631433
    </p>
  </td>
  
  <td>
    631KB
  </td>
  
  <td>
    <p lang="en-US">
      0.322468
    </p>
  </td>
</tr>

<tr>
  <td>
    <p lang="en-US">
      gzip
    </p>
  </td>
  
  <td>
    <p lang="en-US">
      34018
    </p>
  </td>
  
  <td>
    <p lang="en-US">
      34KB
    </p>
  </td>
  
  <td>
    <p lang="en-US">
      0.083316
    </p>
  </td>
</tr>