33import multiprocessing
44import json
55import gzip
6+ from io import BytesIO
67import mimetypes
78
89import psycopg_pool
910import 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
1419app = Bottle ()
@@ -77,70 +82,48 @@ def db_setup():
7782
7883db_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' )
118107def 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' ])
123113def 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>' )
140122def 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' )
156139def 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' )
188171def 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
0 commit comments