@@ -275,6 +275,7 @@ def __init__(self, socket_source: Any) -> None:
275
275
self .routes = {}
276
276
self ._socket_source = socket_source
277
277
self ._sock = None
278
+ self .root_path = "/"
278
279
279
280
def route (self , path : str , method : str = "GET" ):
280
281
"""Decorator used to add a route.
@@ -302,33 +303,50 @@ def serve_forever(self, host: str, port: int = 80, root: str = "") -> None:
302
303
:param int port: port
303
304
:param str root: root directory to serve files from
304
305
"""
305
- self ._sock = self ._socket_source .socket (
306
- self ._socket_source .AF_INET , self ._socket_source .SOCK_STREAM
307
- )
308
- self ._sock .bind ((host , port ))
309
- self ._sock .listen (1 )
306
+ self .start (host , port , root )
310
307
311
308
while True :
312
309
try :
313
- conn , _ = self ._sock . accept ()
310
+ self .poll ()
314
311
except OSError :
315
312
continue
316
- with conn :
317
- # If reading fails, close connection and retry.
318
- try :
319
- length , _ = conn .recvfrom_into (self ._buffer )
320
- except OSError :
321
- continue
322
313
323
- request = _HTTPRequest (raw_request = self ._buffer [:length ])
314
+ def start (self , host : str , port : int = 80 , root : str = "" ) -> None :
315
+ """
316
+ Start the HTTP server at the given host and port. Requires calling
317
+ poll() in a while loop to handle incoming requests.
324
318
325
- # If a route exists for this request, call it. Otherwise try to serve a file.
326
- route = self .routes .get (request , None )
327
- if route :
328
- response = route (request )
329
- elif request .method == "GET" :
330
- response = HTTPResponse (filename = request .path , root = root )
331
- else :
332
- response = HTTPResponse (status = HTTPStatus .INTERNAL_SERVER_ERROR )
319
+ :param str host: host name or IP address
320
+ :param int port: port
321
+ :param str root: root directory to serve files from
322
+ """
323
+ self .root_path = root
324
+
325
+ self ._sock = self ._socket_source .socket (
326
+ self ._socket_source .AF_INET , self ._socket_source .SOCK_STREAM
327
+ )
328
+ self ._sock .bind ((host , port ))
329
+ self ._sock .listen (10 )
333
330
334
- response .send (conn )
331
+ def poll (self ):
332
+ """
333
+ Call this method inside your main event loop to get the server to
334
+ check for new incoming client requests. When a request comes in,
335
+ the application callable will be invoked.
336
+ """
337
+ conn , _ = self ._sock .accept ()
338
+ with conn :
339
+ length , _ = conn .recvfrom_into (self ._buffer )
340
+
341
+ request = _HTTPRequest (raw_request = self ._buffer [:length ])
342
+
343
+ # If a route exists for this request, call it. Otherwise try to serve a file.
344
+ route = self .routes .get (request , None )
345
+ if route :
346
+ response = route (request )
347
+ elif request .method == "GET" :
348
+ response = HTTPResponse (filename = request .path , root = self .root_path )
349
+ else :
350
+ response = HTTPResponse (status = HTTPStatus .INTERNAL_SERVER_ERROR )
351
+
352
+ response .send (conn )
0 commit comments