(此问题不关于来自网络服务器的gzip
- 编码响应的透明解压缩;我知道requests
handles that automatically。)< / p>
我试图将文件发布到RESTful Web服务。显然,requests
使这很容易做到:
files = dict(data=(fn, file))
response = session.post(endpoint_url, files=files)
在这种情况下,我的文件采用高度可压缩的格式(是的,XML),因此我想确保压缩请求正文。
服务器声称在响应头中接受gzip编码(Accept-Encoding: gzip
),所以我应该能够gzip整个身体请求体,对吗?
我试图让这项工作成功:我首先构建请求并准备它,然后我进入PreparedRequest
对象,将body
拉出来,通过{{运行它1}},然后把它放回去。 (哦,不要忘记更新gzip
和Content-Length
标题。)
Content-Encoding
不幸的是,服务器没有合作并返回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
进行请求正文压缩?
编辑:来自@ sigmavirus24 answer的固定(3)和(5)(这些基本上只是我在简化要发布的代码时忽略的工件它在这里)。
答案 0 :(得分:6)
或者我的做法可能有误?
坦白说,我不确定你是如何达到你的方法的,但这肯定是一种更简单的方法。
首先,一些事情:
files
参数构造multipart/form-data
正文。所以你要压缩服务器可能没有任何线索的东西。Content-Encoding
和Transfer-Encoding
是两个非常不同的东西。你想在这里Transfer-Encoding
。NamedTemporaryFile
上设置后缀。multipart/form-data
请求,我将假设您实际上并不想这样做。 session.Request
(我认为应该是requests.Request
)的来电缺少一种方法,即它应该是:requests.Request('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': gzfile.tell(),
'Transfer-Encoding': 'gzip'}
gzfile.seek(0, 0)
response = session.post(endpoint_url, data=gzfile,
headers=headers)
假设file
中包含xml
内容,而您只想压缩它,这应该适合您。您可能想要设置Content-Type
标题,例如,您只需要
headers = {'Content-Length': gzfile.tell(),
'Content-Type': 'application/xml', # or 'text/xml'
'Transfer-Encoding': 'gzip'}
Transfer-Encoding
告诉服务器该请求仅在传输过程中被压缩,并且应该解压缩它。 Content-Type
告诉服务器在处理Transfer-Encoding
后如何处理内容。
答案 1 :(得分:1)
我有question被标记为完全重复。我关注交易的两端。
来自sigmavirus24的代码不是直接剪切和粘贴修复,但它是这个版本的灵感。
以下是我的解决方案的最终结果:
import json
import requests
import StringIO
import gzip
url = "http://localhost:3000"
headers = {"Content-Type":"application/octet-stream"}
data = [{"key": 1,"otherKey": "2"},
{"key": 3,"otherKey": "4"}]
payload = json.dumps(data)
out = StringIO.StringIO()
with gzip.GzipFile(fileobj=out, mode="w") as f:
f.write(json.dumps(data))
out.getvalue()
r = requests.post(url+"/zipped", data=out.getvalue(), headers=headers)
var zlib = require("zlib");
var rawParser = bodyParser.raw({type: '*/*'});
app.post('/zipped', rawParser, function(req, res) {
zlib.gunzip(req.body, function(err, buf) {
if(err){
console.log("err:", err );
} else{
console.log("in the inflate callback:",
buf,
"to string:", buf.toString("utf8") );
}
});
res.status(200).send("I'm in ur zipped route");
});
包含更多详细日志记录的gist here。此版本没有任何内置安全性或检查功能。