Skip to content

Commit e610227

Browse files
Add dynamic port binding
Fixes aio-libs#10665
1 parent 2243281 commit e610227

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

CHANGES/10665.feature.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added `port` accessor for dynamic port allocations in `TCPSite` -- by :user:`twhittock-disguise`.

CONTRIBUTORS.txt

+1
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ Thomas Forbes
344344
Thomas Grainger
345345
Tim Menninger
346346
Tolga Tezel
347+
Tom Whittock
347348
Tomasz Trebski
348349
Toshiaki Tanaka
349350
Trinh Hoang Nhu

aiohttp/web_runner.py

+9
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ def name(self) -> str:
113113
host = "0.0.0.0" if not self._host else self._host
114114
return str(URL.build(scheme=scheme, host=host, port=self._port))
115115

116+
@property
117+
def port(self) -> int:
118+
"""Return the port number the server is bound to, useful for the dynamically allocated port (0)."""
119+
return self._port
120+
116121
async def start(self) -> None:
117122
await super().start()
118123
loop = asyncio.get_event_loop()
@@ -127,6 +132,10 @@ async def start(self) -> None:
127132
reuse_address=self._reuse_address,
128133
reuse_port=self._reuse_port,
129134
)
135+
if self._port == 0:
136+
# Port 0 means bind to any port, so we need to set the attribute
137+
# to the port the server was actually bound to.
138+
self._port = self._server.sockets[0].getsockname()[1]
130139

131140

132141
class UnixSite(BaseSite):

docs/web_advanced.rst

+22
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,28 @@ the middleware might use :meth:`BaseRequest.clone`.
11811181
for modifying *scheme*, *host* and *remote* attributes according
11821182
to ``Forwarded`` and ``X-Forwarded-*`` HTTP headers.
11831183

1184+
Deploying with a dynamic port
1185+
-----------------------------
1186+
1187+
When deploying aiohttp in a zeroconf environment, it may be useful
1188+
to have the server bind to a dynamic port. This can be done by
1189+
using the ``0`` port number. This will cause the OS to assign a
1190+
free port to the server. The assigned port can be retrieved
1191+
using the :attr:`TCPSite.port` property after the server has started.
1192+
1193+
For example::
1194+
1195+
app = web.Application()
1196+
runner = web.AppRunner(app)
1197+
await runner.setup()
1198+
site = web.TCPSite(runner, 'localhost', 0)
1199+
await site.start()
1200+
1201+
print(f"Server started on port {site.port}")
1202+
while True:
1203+
await asyncio.sleep(3600) # sleep forever
1204+
1205+
11841206
Swagger support
11851207
---------------
11861208

0 commit comments

Comments
 (0)