atomic server requests

This commit is contained in:
Devaev Maxim 2019-06-03 15:53:16 +03:00
parent 2977bb1b23
commit 13a51f2f46

View File

@ -155,8 +155,14 @@ _HEADER_AUTH_PASSWD = "X-KVMD-Passwd"
_COOKIE_AUTH_TOKEN = "auth_token" _COOKIE_AUTH_TOKEN = "auth_token"
def _exposed(http_method: str, path: str, auth_required: bool=True) -> Callable: def _atomic(handler: Callable) -> Callable:
def make_wrapper(method: Callable) -> Callable: async def wrap(self: "Server", request: aiohttp.web.Request) -> aiohttp.web.Response:
return (await asyncio.shield(handler(self, request)))
return wrap
def _exposed(http_method: str, path: str, atomic: bool=False, auth_required: bool=True) -> Callable:
def make_wrapper(handler: Callable) -> Callable:
async def wrap(self: "Server", request: aiohttp.web.Request) -> aiohttp.web.Response: async def wrap(self: "Server", request: aiohttp.web.Request) -> aiohttp.web.Response:
try: try:
if auth_required: if auth_required:
@ -180,7 +186,7 @@ def _exposed(http_method: str, path: str, auth_required: bool=True) -> Callable:
else: else:
raise UnauthorizedError("Unauthorized") raise UnauthorizedError("Unauthorized")
return (await method(self, request)) return (await handler(self, request))
except RegionIsBusyError as err: except RegionIsBusyError as err:
return _json_exception(err, 409) return _json_exception(err, 409)
@ -191,6 +197,9 @@ def _exposed(http_method: str, path: str, auth_required: bool=True) -> Callable:
except ForbiddenError as err: except ForbiddenError as err:
return _json_exception(err, 403) return _json_exception(err, 403)
if atomic:
wrap = _atomic(wrap)
setattr(wrap, _ATTR_EXPOSED, True) setattr(wrap, _ATTR_EXPOSED, True)
setattr(wrap, _ATTR_EXPOSED_METHOD, http_method) setattr(wrap, _ATTR_EXPOSED_METHOD, http_method)
setattr(wrap, _ATTR_EXPOSED_PATH, path) setattr(wrap, _ATTR_EXPOSED_PATH, path)
@ -302,7 +311,7 @@ class Server: # pylint: disable=too-many-instance-attributes
# ===== AUTH # ===== AUTH
@_exposed("POST", "/auth/login", auth_required=False) @_exposed("POST", "/auth/login", atomic=True, auth_required=False)
async def __auth_login_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response: async def __auth_login_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response:
credentials = await request.post() credentials = await request.post()
token = await self._auth_manager.login( token = await self._auth_manager.login(
@ -420,7 +429,7 @@ class Server: # pylint: disable=too-many-instance-attributes
async def __hid_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: async def __hid_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
return _json(self.__hid.get_state()) return _json(self.__hid.get_state())
@_exposed("POST", "/hid/reset") @_exposed("POST", "/hid/reset", atomic=True)
async def __hid_reset_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: async def __hid_reset_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
await self.__hid.reset() await self.__hid.reset()
return _json() return _json()
@ -431,7 +440,7 @@ class Server: # pylint: disable=too-many-instance-attributes
async def __atx_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: async def __atx_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
return _json(self.__atx.get_state()) return _json(self.__atx.get_state())
@_exposed("POST", "/atx/power") @_exposed("POST", "/atx/power", atomic=True)
async def __atx_power_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response: async def __atx_power_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response:
action = valid_atx_power_action(request.query.get("action")) action = valid_atx_power_action(request.query.get("action"))
done = await ({ done = await ({
@ -442,7 +451,7 @@ class Server: # pylint: disable=too-many-instance-attributes
}[action])() }[action])()
return _json({"action": action, "done": done}) return _json({"action": action, "done": done})
@_exposed("POST", "/atx/click") @_exposed("POST", "/atx/click", atomic=True)
async def __atx_click_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response: async def __atx_click_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response:
button = valid_atx_button(request.query.get("button")) button = valid_atx_button(request.query.get("button"))
await ({ await ({
@ -458,7 +467,7 @@ class Server: # pylint: disable=too-many-instance-attributes
async def __msd_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: async def __msd_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
return _json(self.__msd.get_state()) return _json(self.__msd.get_state())
@_exposed("POST", "/msd/connect") @_exposed("POST", "/msd/connect", atomic=True)
async def __msd_connect_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response: async def __msd_connect_handler(self, request: aiohttp.web.Request) -> aiohttp.web.Response:
to = valid_kvm_target(request.query.get("to")) to = valid_kvm_target(request.query.get("to"))
return _json(await ({ return _json(await ({
@ -491,7 +500,7 @@ class Server: # pylint: disable=too-many-instance-attributes
logger.info("Written %d bytes to mass-storage device", written) logger.info("Written %d bytes to mass-storage device", written)
return _json({"written": written}) return _json({"written": written})
@_exposed("POST", "/msd/reset") @_exposed("POST", "/msd/reset", atomic=True)
async def __msd_reset_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response: async def __msd_reset_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
await self.__msd.reset() await self.__msd.reset()
return _json() return _json()
@ -538,6 +547,7 @@ class Server: # pylint: disable=too-many-instance-attributes
getattr(method, _ATTR_EXPOSED_PATH), getattr(method, _ATTR_EXPOSED_PATH),
method, method,
) )
return app return app
def __run_app_print(self, text: str) -> None: def __run_app_print(self, text: str) -> None: