Skip to content

Commit 564fa26

Browse files
MehakBindraMehak BindraCopilot
authored
HTTPPlugin : Add a builder option to provide custom server (enables providing options like ssl etc) (#185)
Tested with code like (check running on and activities received on port 8000 ) ``` def make_server(app: FastAPI) -> uvicorn.Server: config = uvicorn.Config( app=app, host="0.0.0.0", port=8000, log_level="debug", ) return uvicorn.Server(config) app = App( plugins=[ DevToolsPlugin(), HttpPlugin(app_id=None, server_factory=make_server), ] ) ``` --------- Co-authored-by: Mehak Bindra <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent fdd62ff commit 564fa26

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

packages/apps/src/microsoft/teams/apps/http_plugin.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,28 @@ def __init__(
6969
app_id: Optional[str],
7070
logger: Optional[Logger] = None,
7171
skip_auth: bool = False,
72+
server_factory: Optional[Callable[[FastAPI], uvicorn.Server]] = None,
7273
):
74+
"""
75+
Args:
76+
app_id: Optional Microsoft App ID.
77+
logger: Optional logger.
78+
skip_auth: Whether to skip JWT validation.
79+
server_factory: Optional function that takes an ASGI app
80+
and returns a configured `uvicorn.Server`.
81+
Example:
82+
```python
83+
def custom_server_factory(app: FastAPI) -> uvicorn.Server:
84+
return uvicorn.Server(config=uvicorn.Config(app, host="0.0.0.0", port=8000))
85+
86+
87+
http_plugin = HttpPlugin(app_id="your-app-id", server_factory=custom_server_factory)
88+
```
89+
"""
7390
super().__init__()
7491
self.logger = logger or ConsoleLogger().create_logger("@teams/http-plugin")
75-
self._server: Optional[uvicorn.Server] = None
7692
self._port: Optional[int] = None
93+
self._server: Optional[uvicorn.Server] = None
7794
self._on_ready_callback: Optional[Callable[[], Awaitable[None]]] = None
7895
self._on_stopped_callback: Optional[Callable[[], Awaitable[None]]] = None
7996

@@ -104,6 +121,14 @@ async def combined_lifespan(app: Starlette):
104121

105122
self.app = FastAPI(lifespan=combined_lifespan)
106123

124+
# Create uvicorn server if user provides custom factory method
125+
if server_factory:
126+
self._server = server_factory(self.app)
127+
if self._server.config.app is not self.app:
128+
raise ValueError(
129+
"server_factory must return a uvicorn.Server configured with the provided FastAPI app instance."
130+
)
131+
107132
# Add JWT validation middleware
108133
if app_id and not skip_auth:
109134
jwt_middleware = create_jwt_validation_middleware(
@@ -144,14 +169,21 @@ def on_stopped_callback(self, callback: Optional[Callable[[], Awaitable[None]]])
144169

145170
async def on_start(self, event: PluginStartEvent) -> None:
146171
"""Start the HTTP server."""
147-
port = event.port
148172
self._port = event.port
149173

150174
try:
151-
config = uvicorn.Config(app=self.app, host="0.0.0.0", port=port, log_level="info")
152-
self._server = uvicorn.Server(config)
175+
if self._server and self._server.config.port != self._port:
176+
self.logger.warning(
177+
"Using port configured by server factory: %d, but plugin start event has port %d.",
178+
self._server.config.port,
179+
self._port,
180+
)
181+
self._port = self._server.config.port
182+
else:
183+
config = uvicorn.Config(app=self.app, host="0.0.0.0", port=self._port, log_level="info")
184+
self._server = uvicorn.Server(config)
153185

154-
self.logger.info("Starting HTTP server on port %d", port)
186+
self.logger.info("Starting HTTP server on port %d", self._port)
155187

156188
# The lifespan handler will call the callback when the server is ready
157189
await self._server.serve()

0 commit comments

Comments
 (0)