Skip to content

Commit 836e8e8

Browse files
committed
[python] bottle: fix bugs
1 parent 67ffd52 commit 836e8e8

2 files changed

Lines changed: 43 additions & 56 deletions

File tree

frameworks/bottle/app.py

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
import multiprocessing
44
import json
55
import gzip
6+
from io import BytesIO
67
import mimetypes
78

89
import psycopg_pool
910
import psycopg.rows
1011

11-
from bottle import Bottle, route, request, response, hook, static_file
12+
import bottle
13+
14+
bottle.BaseRequest.MEMFILE_MAX = 31*1024*1024
15+
16+
from bottle import Bottle, route, request, response, static_file
1217

1318

1419
app = Bottle()
@@ -77,70 +82,48 @@ def db_setup():
7782

7883
db_setup()
7984

80-
81-
# -- framework features ----------------------------------------------------------
82-
83-
@hook('after_request')
84-
def compress_response():
85-
if response.status_code < 200 or response.status_code in (204, 304, 206):
86-
return
8785

88-
accept_encoding = request.headers.get('Accept-Encoding', '')
89-
if 'gzip' not in accept_encoding:
90-
return
86+
# -- Bug Fix for chunked body via gunicorn ---------------------------------------------
9187

92-
if response.headers.get('Content-Encoding'):
93-
return
94-
95-
if response.content_length == 0:
96-
return
97-
98-
body = b''
99-
try:
100-
for chunk in response.body:
101-
if isinstance(chunk, str):
102-
chunk = chunk.encode('utf-8')
103-
body += chunk
104-
response.body.close()
105-
except Exception:
106-
return
107-
108-
compressed_body = gzip.compress(body, compresslevel = 1)
109-
response.body = compressed_body
110-
response.set_header('Content-Encoding', 'gzip')
111-
response.set_header('Content-Length', str(len(compressed_body)))
112-
return
88+
@app.hook('before_request')
89+
def fix_chunked_body():
90+
if request.chunked:
91+
request.environ['HTTP_TRANSFER_ENCODING'] = '_C_H_U_N_K_E_D_'
92+
body = BytesIO()
93+
while True:
94+
chunk = request.environ['wsgi.input'].read(8192)
95+
if not chunk:
96+
break
97+
body.write(chunk)
98+
size = body.tell()
99+
body.seek(0)
100+
request.environ['wsgi.input'] = body
101+
request.environ['CONTENT_LENGTH'] = size
113102

114103

115104
# -- Routes ------------------------------------------------------------------
116105

117-
@app.route('/pipeline')
106+
@app.get('/pipeline')
118107
def pipeline():
108+
response.content_type = 'text/plain; charset=utf-8'
119109
return b'ok'
120110

121111

122-
@app.route('/baseline11', methods=['GET', 'POST'])
112+
@app.route('/baseline11', method=['GET', 'POST'])
123113
def baseline11():
124-
total = 0
125-
try:
126-
total = int(request.query.a)
127-
total = int(request.query.b)
128-
except ValueError:
129-
pass
114+
total = int(request.query.a) + int(request.query.b)
130115
if request.method == 'POST':
131-
try:
132-
total += int(request.body.read(100).strip())
133-
except ValueError:
134-
pass
116+
total += int(request.body.read(100))
117+
response.content_type = 'text/plain; charset=utf-8'
135118
return str(total)
136119

137120

138-
@app.route('/json/<count:int>')
139-
@app.route('/json-comp/<count:int>')
121+
@app.get('/json/<count:int>')
140122
def json_endpoint(count: int):
141123
global DATASET_ITEMS
142124
if not DATASET_ITEMS:
143-
return "No dataset", '500 Internal Server Error'
125+
response.content_type = 'text/plain; charset=utf-8'
126+
return "No dataset", 500
144127
m_val = float(request.query.m)
145128
items = [ ]
146129
for idx, dsitem in enumerate(DATASET_ITEMS):
@@ -152,7 +135,7 @@ def json_endpoint(count: int):
152135
return { 'items': items, 'count': len(items) }
153136

154137

155-
@app.route('/async-db')
138+
@app.get('/async-db')
156139
def async_db_endpoint():
157140
global DATABASE_POOL
158141
if not DATABASE_POOL:
@@ -184,14 +167,19 @@ def async_db_endpoint():
184167
return { "items": [ ], "count": 0 }
185168

186169

187-
@app.route('/upload', methods=['POST'])
170+
@app.post('/upload')
188171
def upload_endpoint():
189172
size = 0
190-
while True:
191-
chunk = request.body.read(256*1024)
192-
if not chunk:
193-
break
194-
size += len(chunk)
173+
try:
174+
body = request.body
175+
while True:
176+
chunk = body.read(256*1024)
177+
if not chunk:
178+
break
179+
size += len(chunk)
180+
except Exception:
181+
pass
182+
response.content_type = 'text/plain; charset=utf-8'
195183
return str(size)
196184

197185

frameworks/bottle/meta.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"display_name": "bottle",
33
"language": "Python",
4-
"type": "production",
4+
"type": "tuned",
55
"engine": "gunicorn",
66
"description": "Fast, simple and lightweight WSGI micro web-framework for Python",
77
"repo": "https://github.com/bottlepy/bottle",
@@ -11,7 +11,6 @@
1111
"pipelined",
1212
"limited-conn",
1313
"json",
14-
"json-comp",
1514
"json-tls",
1615
"upload",
1716
"api-4",

0 commit comments

Comments
 (0)