@@ -194,6 +194,14 @@ class HTTPResponse:
194
194
"\r \n "
195
195
)
196
196
197
+ _CHUNK_HEADERS_FORMAT = (
198
+ "HTTP/1.1 {}\r \n "
199
+ "Content-Type: {}\r \n "
200
+ "Transfer-Encoding: chunked\r \n "
201
+ "Connection: close\r \n "
202
+ "\r \n "
203
+ )
204
+
197
205
def __init__ (
198
206
self ,
199
207
* ,
@@ -244,6 +252,22 @@ def send(self, conn: Any) -> None:
244
252
else :
245
253
self ._send_response (conn , self .status , self .content_type , self .body , self .cache )
246
254
255
+ def send_chunk_headers (self , conn : Any ):
256
+ """Send Headers for a chunked response over the given socket."""
257
+ self ._send_bytes (
258
+ conn , self ._CHUNK_HEADERS_FORMAT .format (self .status , self .content_type )
259
+ )
260
+
261
+ def send_body_chunk (self , conn : Any , chunk : str ):
262
+ """Send chunk of data to the given socket. Send an empty("") chunk to finish the session.
263
+
264
+ :param Any conn: Current connection.
265
+ :param str chunk: String data to be sent.
266
+ """
267
+ size = "%X\r \n " .encode () % len (chunk )
268
+ self ._send_bytes (conn , size )
269
+ self ._send_bytes (conn , chunk .encode () + b'\r \n ' )
270
+
247
271
def _send_response (self , conn , status , content_type , body , cache ):
248
272
self ._send_bytes (
249
273
conn , self ._HEADERS_FORMAT .format (status , content_type , len (body ), cache )
@@ -305,7 +329,17 @@ def route_func(request):
305
329
raw_text = request.raw_request.decode("utf8")
306
330
print("Received a request of length", len(raw_text), "bytes")
307
331
return HTTPResponse(body="hello world")
308
-
332
+
333
+ @server.route(path, method)
334
+ def route_func(request, conn):
335
+ raw_text = request.raw_request.decode("utf8")
336
+ print("Received a request of length", len(raw_text), "bytes")
337
+ res = HTTPResponse(content_type="text/html")
338
+ res.send_chunk_headers(conn)
339
+ res.send_body_chunk(conn, "Some content")
340
+ res.send_body_chunk(conn, "Some more content")
341
+ res.send_body_chunk(conn, "") # Send empty packet to finish chunked stream
342
+ return None # Return None, so server knows that nothing else needs to be sent.
309
343
"""
310
344
311
345
def route_decorator (func : Callable ) -> Callable :
@@ -364,7 +398,13 @@ def poll(self):
364
398
# If a route exists for this request, call it. Otherwise try to serve a file.
365
399
route = self .routes .get (request , None )
366
400
if route :
367
- response = route (request )
401
+ # Use try, so we don't break old api of this lib.
402
+ try :
403
+ response = route (request , conn )
404
+ except TypeError :
405
+ response = route (request )
406
+ if response is None :
407
+ return
368
408
elif request .method == "GET" :
369
409
response = HTTPResponse (filename = request .path , cache = 604800 , root = self .root_path )
370
410
else :
0 commit comments