python - 使用 python-requests 压缩请求体?

标签 python http gzip python-requests

(这个问题不是关于 gzip 编码的 responses 来自网络服务器的透明解压;我知道 requests handles that automatically。)

问题

我正在尝试将文件发布到 RESTful 网络服务。显然,requests 使这很容易做到:

files = dict(data=(fn, file))
response = session.post(endpoint_url, files=files)

在这种情况下,我的文件采用高度可压缩的格式(是的,XML),因此我想确保压缩请求正文。

服务器声称接受 gzip 编码(Accept-Encoding: gzip 在响应 header 中),所以我应该能够 gzip 整个请求体,对吧?

尝试的解决方案

这是我尝试完成这项工作的尝试:我首先构造请求并准备它,然后我进入 PreparedRequest 对象,抽出 body,运行它gzip,然后放回去。 (哦,不要忘记更新 Content-LengthContent-Encoding header 。)

files = dict(data=(fn, file))
request = request.Request('POST',endpoint_url, files=files)

prepped = session.prepare_request(request)
with NamedTemporaryFile(delete=True) as gzfile:
    gzip.GzipFile(fileobj=gzfile, mode="wb").write(prepped.body)
    prepped.headers['Content-Length'] = gzfile.tell()
    prepped.headers['Content-Encoding'] = 'gzip'
    gzfile.seek(0,0)
    prepped.body = gzfile.read()
    response = session.send(prepped)

不幸的是,服务器不合作并返回 500 Internal Server Error。也许它真的不接受 gzip 编码的请求?

或者我的方法有误?好像比较绕。有没有更简单的方法来使用 python-requests 进行请求正文压缩?

编辑: 修复了@sigmavirus24 的 answer 中的 (3) 和 (5) (这些基本上只是我在简化代码以在此处发布时忽略的工件)。

最佳答案

Or perhaps there is a mistake in my approach?

坦率地说,我不确定您是如何得出您的方法的,但肯定有一种更简单的方法可以做到这一点。

首先,有几点:

  1. files 参数构造了一个multipart/form-data 主体。因此,您正在压缩服务器可能不知道的内容。
  2. Content-EncodingTransfer-Encoding 是两个截然不同的东西。您需要在此处使用 Transfer-Encoding
  3. 您不需要在 NamedTemporaryFile 上设置后缀。
  4. 由于您没有明确提到您正在尝试压缩 multipart/form-data 请求,因此我假设您实际上并不想这样做。
  5. 您对 session.Request 的调用(我假设应该是 requests.Request)缺少一个方法,即它应该是:requests。请求('POST', endpoint_url, ...)

有了这些,下面是我将如何做到这一点:

# Assuming `file` is a file-like obj
with NamedTemporaryFile(delete=True) as gzfile:
    gzip.GzipFile(fileobj=gzfile, mode="wb").write(file.read())
    headers = {'Content-Length': str(gzfile.tell()),
               'Transfer-Encoding': 'gzip'}
    gzfile.seek(0, 0)
    response = session.post(endpoint_url, data=gzfile, 
                            headers=headers)

假设 file 中有 xml 内容,而您的意思是压缩它,这应该适合您。你可能想要设置一个 Content-Type header ,例如,你可以这样做

 headers = {'Content-Length': gzfile.tell(),
            'Content-Type': 'application/xml',  # or 'text/xml'
            'Transfer-Encoding': 'gzip'}

Transfer-Encoding 告诉服务器请求只在传输过程中被压缩,它应该解压它。 Content-Type 告诉服务器在处理完 Transfer-Encoding 后如何处理内容。

关于python - 使用 python-requests 压缩请求体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28656068/

相关文章:

http - 在哪里可以找到所有可能的 "Connection" header 值?

compression - Node.js:Gzip 压缩?

jquery - 如何使用 ASP 压缩 JSON?

python - youtube-dl 完成下载时运行异步函数(python)

python - 在 Python 中使用 JSON 将查询发送到 MongoDB

http - 警告 HTTP header - 合法代理字符串格式

Erlang 中的 HTTP 爬虫

http - 禁用从服务器接收到的带有错误 header 的 HTTP 正文的解压缩

python - Google App Engine 上的 Facebook 注册

python - python中的k均值聚类实现,内存不足