File upload Nginx+;龙卷风(+;卷曲):充气压缩后请求

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

我已经设置了一台运行Tornado(版本2.4.1)并由Nginx(版本1.4.4)代理的服务器(两台服务器,但我认为这与这个问题不太相关)

我需要定期通过
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