Skip to content

Commit f438c03

Browse files
committed
Fix #165 by making AsyncApp compatible with aiohttp-devtools
1 parent c8b28df commit f438c03

File tree

5 files changed

+85
-20
lines changed

5 files changed

+85
-20
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# ------------------------------------------------
2+
# instead of slack_bolt in requirements.txt
3+
import sys
4+
5+
sys.path.insert(1, "../..")
6+
# ------------------------------------------------
7+
8+
import logging
9+
10+
logging.basicConfig(level=logging.DEBUG)
11+
12+
from slack_bolt.async_app import AsyncApp
13+
14+
app = AsyncApp()
15+
16+
17+
@app.event("app_mention")
18+
async def event_test(body, say, logger):
19+
logger.info(body)
20+
await say("What's up?")
21+
22+
23+
@app.command("/hello-bolt-python")
24+
# or app.command(re.compile(r"/hello-.+"))(test_command)
25+
async def command(ack, body):
26+
user_id = body["user_id"]
27+
await ack(f"Hi <@{user_id}>!")
28+
29+
30+
def app_factory():
31+
return app.web_app()
32+
33+
34+
# pip install -r requirements.txt
35+
# export SLACK_SIGNING_SECRET=***
36+
# export SLACK_BOT_TOKEN=xoxb-***
37+
# adev runserver --port 3000 --app-factory app_factory async_app.py
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
aiohttp>=3,<4
2+
aiohttp-devtools>=0.13,<0.14

slack_bolt/app/async_app.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import os
44
from typing import Optional, List, Union, Callable, Pattern, Dict, Awaitable, Sequence
55

6+
from aiohttp import web
7+
8+
from slack_bolt.app.async_server import AsyncSlackAppServer
69
from slack_bolt.listener.asyncio_runner import AsyncioListenerRunner
710
from slack_bolt.middleware.message_listener_matches.async_message_listener_matches import (
811
AsyncMessageListenerMatches,
@@ -225,6 +228,8 @@ def __init__(
225228
self._init_middleware_list_done = False
226229
self._init_async_middleware_list()
227230

231+
self._server: Optional[AsyncSlackAppServer] = None
232+
228233
def _init_async_middleware_list(self):
229234
if self._init_middleware_list_done:
230235
return
@@ -282,17 +287,36 @@ def listener_runner(self) -> AsyncioListenerRunner:
282287
# -------------------------
283288
# standalone server
284289

290+
from .async_server import AsyncSlackAppServer
291+
292+
def server(
293+
self, port: int = 3000, path: str = "/slack/events"
294+
) -> AsyncSlackAppServer:
295+
"""Configure a web server using AIOHTTP.
296+
297+
:param port: The port to listen on (Default: 3000)
298+
:param path: The path to handle request from Slack (Default: /slack/events)
299+
:return: None
300+
"""
301+
if (
302+
self._server is None
303+
or self._server.port != port
304+
or self._server.path != path
305+
):
306+
self._server = AsyncSlackAppServer(port=port, path=path, app=self,)
307+
return self._server
308+
309+
def web_app(self, path: str = "/slack/events") -> web.Application:
310+
return self.server(path=path).web_app
311+
285312
def start(self, port: int = 3000, path: str = "/slack/events") -> None:
286313
"""Start a web server using AIOHTTP.
287314
288315
:param port: The port to listen on (Default: 3000)
289316
:param path: The path to handle request from Slack (Default: /slack/events)
290317
:return: None
291318
"""
292-
from .async_server import AsyncSlackAppServer
293-
294-
self.server = AsyncSlackAppServer(port=port, path=path, app=self,)
295-
self.server.start()
319+
self.server(port=port, path=path).start()
296320

297321
# -------------------------
298322
# main dispatcher

slack_bolt/app/async_server.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,24 @@
77

88

99
class AsyncSlackAppServer:
10+
port: int
11+
path: str
12+
bolt_app: "AsyncApp"
13+
web_app: web.Application
14+
1015
def __init__(
11-
self, port: int, path: str, app, # AsyncApp
16+
self, port: int, path: str, app: "AsyncApp",
1217
):
1318
"""Standalone AIOHTTP Web Server
1419
1520
Refer to AIOHTTP documents for details.
1621
https://docs.aiohttp.org/en/stable/web.html
1722
"""
18-
self._port = port
19-
self._endpoint_path = path
20-
self._bolt_app: "AsyncApp" = app
21-
23+
self.port = port
24+
self.path = path
25+
self.bolt_app: "AsyncApp" = app
2226
self.web_app = web.Application()
23-
self._bolt_oauth_flow = self._bolt_app.oauth_flow
27+
self._bolt_oauth_flow = self.bolt_app.oauth_flow
2428
if self._bolt_oauth_flow:
2529
self.web_app.add_routes(
2630
[
@@ -31,13 +35,11 @@ def __init__(
3135
self._bolt_oauth_flow.redirect_uri_path,
3236
self.handle_get_requests,
3337
),
34-
web.post(self._endpoint_path, self.handle_post_requests),
38+
web.post(self.path, self.handle_post_requests),
3539
]
3640
)
3741
else:
38-
self.web_app.add_routes(
39-
[web.post(self._endpoint_path, self.handle_post_requests)]
40-
)
42+
self.web_app.add_routes([web.post(self.path, self.handle_post_requests)])
4143

4244
async def handle_get_requests(self, request: web.Request) -> web.Response:
4345
oauth_flow = self._bolt_oauth_flow
@@ -56,21 +58,21 @@ async def handle_get_requests(self, request: web.Request) -> web.Response:
5658
return web.Response(status=404)
5759

5860
async def handle_post_requests(self, request: web.Request) -> web.Response:
59-
if self._endpoint_path != request.path:
61+
if self.path != request.path:
6062
return web.Response(status=404)
6163

6264
bolt_req = await to_bolt_request(request)
63-
bolt_resp: BoltResponse = await self._bolt_app.async_dispatch(bolt_req)
65+
bolt_resp: BoltResponse = await self.bolt_app.async_dispatch(bolt_req)
6466
return await to_aiohttp_response(bolt_resp)
6567

6668
def start(self) -> None:
6769
""" Starts a new web server process.
6870
6971
:return: None
7072
"""
71-
if self._bolt_app.logger.level > logging.INFO:
73+
if self.bolt_app.logger.level > logging.INFO:
7274
print("⚡️ Bolt app is running!")
7375
else:
74-
self._bolt_app.logger.info("⚡️ Bolt app is running!")
76+
self.bolt_app.logger.info("⚡️ Bolt app is running!")
7577

76-
web.run_app(self.web_app, host="0.0.0.0", port=self._port)
78+
web.run_app(self.web_app, host="0.0.0.0", port=self.port)

tests/mock_web_api_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def run(self):
168168
self.server = HTTPServer(("localhost", 8888), self.handler)
169169
self.test.mock_received_requests = self.handler.received_requests
170170
self.test.server_url = "http://localhost:8888"
171-
self.test.host, self.test._port = self.server.socket.getsockname()
171+
self.test.host, self.test.port = self.server.socket.getsockname()
172172
self.test.server_started.set() # threading.Event()
173173

174174
self.test = None

0 commit comments

Comments
 (0)