Skip to content

Commit eba7a91

Browse files
committed
Added Server.stop
1 parent cd8146e commit eba7a91

File tree

3 files changed

+27
-3
lines changed

3 files changed

+27
-3
lines changed

adafruit_httpserver/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
"""
99

1010

11+
class ServerStoppedError(Exception):
12+
"""
13+
Raised when ``.poll`` is called on a stopped ``Server``.
14+
"""
15+
16+
1117
class AuthenticationError(Exception):
1218
"""
1319
Raised by ``require_authentication`` when the ``Request`` is not authorized.

adafruit_httpserver/server.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from .authentication import Basic, Bearer, require_authentication
2020
from .exceptions import (
21+
ServerStoppedError,
2122
AuthenticationError,
2223
FileNotExistsError,
2324
InvalidPathError,
@@ -47,6 +48,7 @@ def __init__(self, socket_source: Protocol, root_path: str = None) -> None:
4748
self._socket_source = socket_source
4849
self._sock = None
4950
self.root_path = root_path
51+
self.stopped = False
5052

5153
def route(self, path: str, methods: Union[str, List[str]] = GET) -> Callable:
5254
"""
@@ -91,13 +93,14 @@ def serve_forever(self, host: str, port: int = 80) -> None:
9193
"""
9294
Wait for HTTP requests at the given host and port. Does not return.
9395
Ignores any exceptions raised by the handler function and continues to serve.
96+
Returns only when the server is stopped by calling ``.stop()``.
9497
9598
:param str host: host name or IP address
9699
:param int port: port
97100
"""
98101
self.start(host, port)
99102

100-
while "Serving forever":
103+
while not self.stopped:
101104
try:
102105
self.poll()
103106
except: # pylint: disable=bare-except
@@ -106,17 +109,27 @@ def serve_forever(self, host: str, port: int = 80) -> None:
106109
def start(self, host: str, port: int = 80) -> None:
107110
"""
108111
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.
110113
111114
:param str host: host name or IP address
112115
:param int port: port
113116
"""
117+
self.stopped = False
114118
self._sock = self._socket_source.socket(
115119
self._socket_source.AF_INET, self._socket_source.SOCK_STREAM
116120
)
117121
self._sock.bind((host, port))
118122
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()
120133

121134
def _receive_request(
122135
self,
@@ -230,6 +243,9 @@ def poll(self):
230243
Call this method inside your main loop to get the server to check for new incoming client
231244
requests. When a request comes in, it will be handled by the handler function.
232245
"""
246+
if self.stopped:
247+
raise ServerStoppedError
248+
233249
try:
234250
conn, client_address = self._sock.accept()
235251
with conn:

examples/httpserver_start_and_poll.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ def base(request: Request):
3434

3535
# Process any waiting requests
3636
server.poll()
37+
38+
# If you want you can stop the server by calling server.stop() anywhere in your code
3739
except OSError as error:
3840
print(error)
3941
continue

0 commit comments

Comments
 (0)