web_server.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """Low level HTTP server."""
  2. import asyncio
  3. from typing import Any, Awaitable, Callable, Dict, List, Optional # noqa
  4. from .abc import AbstractStreamWriter
  5. from .helpers import get_running_loop
  6. from .http_parser import RawRequestMessage
  7. from .streams import StreamReader
  8. from .web_protocol import RequestHandler, _RequestFactory, _RequestHandler
  9. from .web_request import BaseRequest
  10. __all__ = ("Server",)
  11. class Server:
  12. def __init__(
  13. self,
  14. handler: _RequestHandler,
  15. *,
  16. request_factory: Optional[_RequestFactory] = None,
  17. loop: Optional[asyncio.AbstractEventLoop] = None,
  18. **kwargs: Any
  19. ) -> None:
  20. self._loop = get_running_loop(loop)
  21. self._connections = {} # type: Dict[RequestHandler, asyncio.Transport]
  22. self._kwargs = kwargs
  23. self.requests_count = 0
  24. self.request_handler = handler
  25. self.request_factory = request_factory or self._make_request
  26. @property
  27. def connections(self) -> List[RequestHandler]:
  28. return list(self._connections.keys())
  29. def connection_made(
  30. self, handler: RequestHandler, transport: asyncio.Transport
  31. ) -> None:
  32. self._connections[handler] = transport
  33. def connection_lost(
  34. self, handler: RequestHandler, exc: Optional[BaseException] = None
  35. ) -> None:
  36. if handler in self._connections:
  37. del self._connections[handler]
  38. def _make_request(
  39. self,
  40. message: RawRequestMessage,
  41. payload: StreamReader,
  42. protocol: RequestHandler,
  43. writer: AbstractStreamWriter,
  44. task: "asyncio.Task[None]",
  45. ) -> BaseRequest:
  46. return BaseRequest(message, payload, protocol, writer, task, self._loop)
  47. async def shutdown(self, timeout: Optional[float] = None) -> None:
  48. coros = [conn.shutdown(timeout) for conn in self._connections]
  49. await asyncio.gather(*coros)
  50. self._connections.clear()
  51. def __call__(self) -> RequestHandler:
  52. return RequestHandler(self, loop=self._loop, **self._kwargs)