context.py 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # coding: utf-8
  2. import asyncio
  3. import typing
  4. from http import HTTPStatus
  5. from json import JSONDecodeError
  6. from aiohttp.web_request import Request
  7. from aiohttp.web_response import Response
  8. from multidict import MultiDict
  9. from hapic.context import BaseContext
  10. from hapic.context import RouteRepresentation
  11. from hapic.decorator import DecoratedController
  12. from hapic.exception import WorkflowException
  13. from hapic.processor import ProcessValidationError
  14. from hapic.processor import RequestParameters
  15. from aiohttp import web
  16. class AiohttpRequestParameters(object):
  17. def __init__(
  18. self,
  19. request: Request,
  20. ) -> None:
  21. self._request = request
  22. self._parsed_body = None
  23. @property
  24. async def body_parameters(self) -> dict:
  25. if self._parsed_body is None:
  26. content_type = self.header_parameters.get('Content-Type')
  27. is_json = content_type == 'application/json'
  28. if is_json:
  29. self._parsed_body = await self._request.json()
  30. else:
  31. self._parsed_body = await self._request.post()
  32. return self._parsed_body
  33. @property
  34. def path_parameters(self):
  35. return dict(self._request.match_info)
  36. @property
  37. def query_parameters(self):
  38. return MultiDict(self._request.query.items())
  39. @property
  40. def form_parameters(self):
  41. # TODO BS 2018-07-24: There is misunderstanding around body/form/json
  42. return self.body_parameters
  43. @property
  44. def header_parameters(self):
  45. return dict(self._request.headers.items())
  46. @property
  47. def files_parameters(self):
  48. # TODO BS 2018-07-24: To do
  49. raise NotImplementedError('todo')
  50. class AiohttpContext(BaseContext):
  51. def __init__(
  52. self,
  53. app: web.Application,
  54. ) -> None:
  55. self._app = app
  56. @property
  57. def app(self) -> web.Application:
  58. return self._app
  59. def get_request_parameters(
  60. self,
  61. *args,
  62. **kwargs
  63. ) -> RequestParameters:
  64. try:
  65. request = args[0]
  66. except IndexError:
  67. raise WorkflowException(
  68. 'Unable to get aiohttp request object',
  69. )
  70. request = typing.cast(Request, request)
  71. return AiohttpRequestParameters(request)
  72. def get_response(
  73. self,
  74. response: str,
  75. http_code: int,
  76. mimetype: str = 'application/json',
  77. ) -> typing.Any:
  78. return Response(
  79. body=response,
  80. status=http_code,
  81. content_type=mimetype,
  82. )
  83. def get_validation_error_response(
  84. self,
  85. error: ProcessValidationError,
  86. http_code: HTTPStatus = HTTPStatus.BAD_REQUEST,
  87. ) -> typing.Any:
  88. # TODO BS 2018-07-24: To do
  89. raise NotImplementedError('todo')
  90. def find_route(
  91. self,
  92. decorated_controller: DecoratedController,
  93. ) -> RouteRepresentation:
  94. pass
  95. def get_swagger_path(
  96. self,
  97. contextualised_rule: str,
  98. ) -> str:
  99. pass
  100. def by_pass_output_wrapping(
  101. self,
  102. response: typing.Any,
  103. ) -> bool:
  104. pass
  105. def add_view(
  106. self,
  107. route: str,
  108. http_method: str,
  109. view_func: typing.Callable[..., typing.Any],
  110. ) -> None:
  111. pass
  112. def serve_directory(
  113. self,
  114. route_prefix: str,
  115. directory_path: str,
  116. ) -> None:
  117. pass
  118. def is_debug(
  119. self,
  120. ) -> bool:
  121. pass
  122. def handle_exception(
  123. self,
  124. exception_class: typing.Type[Exception],
  125. http_code: int,
  126. ) -> None:
  127. pass
  128. def handle_exceptions(
  129. self,
  130. exception_classes: typing.List[typing.Type[Exception]],
  131. http_code: int,
  132. ) -> None:
  133. pass