18
18
19
19
from .authentication import Basic , Bearer , require_authentication
20
20
from .exceptions import (
21
+ ServerStoppedError ,
21
22
AuthenticationError ,
22
23
FileNotExistsError ,
23
24
InvalidPathError ,
@@ -47,6 +48,7 @@ def __init__(self, socket_source: Protocol, root_path: str = None) -> None:
47
48
self ._socket_source = socket_source
48
49
self ._sock = None
49
50
self .root_path = root_path
51
+ self .stopped = False
50
52
51
53
def route (self , path : str , methods : Union [str , List [str ]] = GET ) -> Callable :
52
54
"""
@@ -91,13 +93,14 @@ def serve_forever(self, host: str, port: int = 80) -> None:
91
93
"""
92
94
Wait for HTTP requests at the given host and port. Does not return.
93
95
Ignores any exceptions raised by the handler function and continues to serve.
96
+ Returns only when the server is stopped by calling ``.stop()``.
94
97
95
98
:param str host: host name or IP address
96
99
:param int port: port
97
100
"""
98
101
self .start (host , port )
99
102
100
- while "Serving forever" :
103
+ while not self . stopped :
101
104
try :
102
105
self .poll ()
103
106
except : # pylint: disable=bare-except
@@ -106,17 +109,27 @@ def serve_forever(self, host: str, port: int = 80) -> None:
106
109
def start (self , host : str , port : int = 80 ) -> None :
107
110
"""
108
111
Start the HTTP server at the given host and port. Requires calling
109
- poll() in a while loop to handle incoming requests.
112
+ ``. poll()`` in a while loop to handle incoming requests.
110
113
111
114
:param str host: host name or IP address
112
115
:param int port: port
113
116
"""
117
+ self .stopped = False
114
118
self ._sock = self ._socket_source .socket (
115
119
self ._socket_source .AF_INET , self ._socket_source .SOCK_STREAM
116
120
)
117
121
self ._sock .bind ((host , port ))
118
122
self ._sock .listen (10 )
119
- self ._sock .setblocking (False ) # non-blocking socket
123
+ self ._sock .setblocking (False ) # Non-blocking socket
124
+
125
+ def stop (self ) -> None :
126
+ """
127
+ Stops the server from listening for new connections and closes the socket.
128
+ Current requests will be processed. Server can be started again by calling ``.start()``
129
+ or ``.serve_forever()``.
130
+ """
131
+ self .stopped = True
132
+ self ._sock .close ()
120
133
121
134
def _receive_request (
122
135
self ,
@@ -230,6 +243,9 @@ def poll(self):
230
243
Call this method inside your main loop to get the server to check for new incoming client
231
244
requests. When a request comes in, it will be handled by the handler function.
232
245
"""
246
+ if self .stopped :
247
+ raise ServerStoppedError
248
+
233
249
try :
234
250
conn , client_address = self ._sock .accept ()
235
251
with conn :
0 commit comments