File upload Nginx+;龙卷风(+;卷曲):充气压缩后请求
我已经设置了一台运行Tornado(版本2.4.1)并由Nginx(版本1.4.4)代理的服务器(两台服务器,但我认为这与这个问题不太相关) 我需要定期通过File upload Nginx+;龙卷风(+;卷曲):充气压缩后请求,file-upload,curl,nginx,tornado,http-compression,File Upload,Curl,Nginx,Tornado,Http Compression,我已经设置了一台运行Tornado(版本2.4.1)并由Nginx(版本1.4.4)代理的服务器(两台服务器,但我认为这与这个问题不太相关) 我需要定期通过POST请求将json(基本上是文本)文件上传到其中一个。这些文件将大大受益于gzip压缩(当我手动压缩文件时,压缩率达到90%),但我不知道如何以一种好的方式将它们膨胀 理想情况下,Nginx会将其充气,并将其干净地传递给龙卷风。。。但正如你可能已经猜到的那样,这不是现在发生的事情,否则我就不会问这个问题:-) 这些是我的nginx.con
POST
请求将json
(基本上是文本)文件上传到其中一个。这些文件将大大受益于gzip压缩(当我手动压缩文件时,压缩率达到90%),但我不知道如何以一种好的方式将它们膨胀
理想情况下,Nginx会将其充气,并将其干净地传递给龙卷风。。。但正如你可能已经猜到的那样,这不是现在发生的事情,否则我就不会问这个问题:-)
这些是我的nginx.conf
文件的相关部分(或者我认为相关的部分,因为我对nginx和Tornado非常陌生):
正如我前面提到的,有两个Tornado服务器。主要的一个是运行在localhost:8000
上的网页之类的东西。运行在localhost:8200
上的是用于接收那些json
文件的程序。除了Gzip部分之外,此设置工作正常
我希望Nginx对到达localhost:81
的gzip请求进行膨胀,并将它们转发到我在localhost:8200
上运行的Tornado(膨胀)
通过这样的配置,数据到达Tornado,但身体仍然被压缩,Tornado抛出一个异常:
[E 140108 15:33:42 input:1085] Uncaught exception POST
/input/log?ts=1389213222 (127.0.0.1)
HTTPRequest(
protocol='http', host='192.168.0.140:81',
method='POST', uri='/input/log?&ts=1389213222',
version='HTTP/1.0', remote_ip='127.0.0.1', body='\x1f\x8b\x08\x00\x00',
headers={'Content-Length': '1325', 'Accept-Encoding': 'deflate, gzip',
'Content-Encoding': 'gzip', 'Host': '192.168.0.140:81', 'Accept': '*/*',
'User-Agent': 'curl/7.23.1 libcurl/7.23.1 OpenSSL/1.0.1c zlib/1.2.7',
'Connection': 'close', 'X-Real-Ip': '192.168.0.94',
'Content-Type': 'application/json'}
)
我知道我总是可以在post()
Tornado处理程序中获取请求的正文
,并手动将其充气,但这听起来。。。肮脏的
最后,这是我用来上传gzip文件的curl
调用:
curl --max-time 60 --silent --location --insecure \
--write-out "%{http_code}" --request POST \
--compressed \
--header "Content-Encoding:gzip" \
--header "Content-Type:application/json" \
--data-binary "$log_file_path.gz" \
"/input/log?ts=1389216192" \
--output /dev/null \
--trace-ascii "/tmp/curl_trace.log" \
--connect-timeout 30
$log\u file\u path.gz
中的文件是使用gzip$log\u file\u path
生成的(我的意思是…是一个常规的gzip压缩文件)
这是可行的吗?听起来应该很直截了当,但不是
<>如果这是NGIX不可行的,龙卷风中的自动化方法也会工作(更可靠和优雅,让我在POST请求处理程序中间压缩文件),比如…像Django Middleware之类的东西
提前谢谢你 您已经在某处调用了
json.loads()
(Tornado没有为您解码json,因此您看到的异常(但没有引用)必须来自您自己的代码);为什么不用检查内容编码
和内容类型
标题并进行适当解码的方法来取代它呢?我放弃了让Nginx或Tornado自动扩展POST请求主体的尝试,所以我选择了Ben Darnell在回答中提到的方法。我使用gzip压缩文件,并将其作为表单的一部分发布(就像我上传文件一样)
我将发布处理它的代码片段,以防这对其他人有所帮助:
在客户端中(使用curl的bash脚本):
try:
content_type = self.request.files['data'][0]['content_type']
if content_type == 'application/x-gzip':
gzip_decompressor = GzipDecompressor()
file_body = gzip_decompressor.decompress(
self.request.files['data'][0]['body'])
file_body += gzip_decompressor.flush()
else:
file_body = self.request.files['data'][0]['body']
except:
self.send_error(400)
logging.error('Failed to interpret data: %s',
self.request.files['data'])
return
要发送的文件的路径(绝对路径)位于变量f
中。变量TMP\u DIR
指向/TMP/
,并且SCRIPT\u NAME
包含尝试执行上载的bash脚本的名称(即uploader.sh
)
在服务器中(在Tornado处理程序中):
try:
content_type = self.request.files['data'][0]['content_type']
if content_type == 'application/x-gzip':
gzip_decompressor = GzipDecompressor()
file_body = gzip_decompressor.decompress(
self.request.files['data'][0]['body'])
file_body += gzip_decompressor.flush()
else:
file_body = self.request.files['data'][0]['body']
except:
self.send_error(400)
logging.error('Failed to interpret data: %s',
self.request.files['data'])
return
谢谢你的回答,但是如果我在curl调用中删除Content-Type头,它就会继续发生。即使是这样,我不应该在例外情况下看到一个膨胀的身体吗?我没有说改变请求;我说要修改你的代码来解压你收到的数据。由于json解码已经存在于您的代码中,而不是框架中(如果您从tornado而不是您自己的代码中获得异常,请发布回溯),将解压放在一些神奇的“中间件”中没有任何好处。因此,你的建议是把request.body放在龙卷风处理程序中,然后用我自己的代码将其膨胀?我有点想避免这种情况,让Nginx(或Tornado)以透明的方式膨胀请求。是的。您已经在代码中调用了json.loads(request.body),对吗?我是,我是。。。我想做的是让request.body自动解压缩。问题不是json,问题是主体在到达json时仍然是gzip
try:
content_type = self.request.files['data'][0]['content_type']
if content_type == 'application/x-gzip':
gzip_decompressor = GzipDecompressor()
file_body = gzip_decompressor.decompress(
self.request.files['data'][0]['body'])
file_body += gzip_decompressor.flush()
else:
file_body = self.request.files['data'][0]['body']
except:
self.send_error(400)
logging.error('Failed to interpret data: %s',
self.request.files['data'])
return