@@ -275,6 +275,7 @@ def __init__(self, socket_source: Any) -> None:
275275 self .routes = {}
276276 self ._socket_source = socket_source
277277 self ._sock = None
278+ self .root_path = "/"
278279
279280 def route (self , path : str , method : str = "GET" ):
280281 """Decorator used to add a route.
@@ -302,33 +303,50 @@ def serve_forever(self, host: str, port: int = 80, root: str = "") -> None:
302303 :param int port: port
303304 :param str root: root directory to serve files from
304305 """
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 )
310307
311308 while True :
312309 try :
313- conn , _ = self ._sock . accept ()
310+ self .poll ()
314311 except OSError :
315312 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
322313
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.
324318
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 )
333330
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