async def userCreate(request): session = request.ctx.session form = request.json authId = getattr(session, 'authId', None) if authId is None: raise Forbidden('anonymous') form['authorization'] = authId user = await User.get_or_none(authId=authId) if user is not None: raise Forbidden('exists') try: async with request.app.ctx.usermgrd.post('http://localhost/', json=form) as resp: data = await resp.json() if data['status'] != 'ok': request.ctx.logger.error(__name__ + '.create.usermgrd_error', reason=data['status']) raise ServerError('backend') except aiohttp.ClientConnectionError: request.ctx.logger.error(__name__ + '.create.usermgrd_connect_failure') raise ServiceUnavailable('backend') user = User(authId=authId, name=data['user']) user.password = data['password'] await user.save() request.ctx.logger.info(__name__ + '.create', user=user.name) return await makeUserResponse(user)
def check_timeouts(self): """ Runs itself periodically to enforce any expired timeouts. """ try: if not self._task: return duration = current_time() - self._time stage = self._http.stage if stage is Stage.IDLE and duration > self.keep_alive_timeout: logger.debug("KeepAlive Timeout. Closing connection.") elif stage is Stage.REQUEST and duration > self.request_timeout: logger.debug("Request Timeout. Closing connection.") self._http.exception = RequestTimeout("Request Timeout") elif stage is Stage.HANDLER and self._http.upgrade_websocket: logger.debug("Handling websocket. Timeouts disabled.") return elif (stage in (Stage.HANDLER, Stage.RESPONSE, Stage.FAILED) and duration > self.response_timeout): logger.debug("Response Timeout. Closing connection.") self._http.exception = ServiceUnavailable("Response Timeout") else: interval = (min( self.keep_alive_timeout, self.request_timeout, self.response_timeout, ) / 2) self.loop.call_later(max(0.1, interval), self.check_timeouts) return self._task.cancel() except Exception: error_logger.exception("protocol.check_timeouts")
async def post(self, _: Request, model_id: str): self._logger.debug(f"Training model : {model_id}.") try: self._spacy_manager.update_model(model_id) except ModelIsUpdatingException as e: raise ServiceUnavailable(e) return response.text("Successfully triggered a training run.", status=202)
async def http1(self): """ HTTP 1.1 connection handler """ while True: # As long as connection stays keep-alive try: # Receive and handle a request self.stage = Stage.REQUEST self.response_func = self.http1_response_header await self.http1_request_header() self.request.conn_info = self.protocol.conn_info await self.protocol.request_handler(self.request) # Handler finished, response should've been sent if self.stage is Stage.HANDLER and not self.upgrade_websocket: raise ServerError("Handler produced no response") if self.stage is Stage.RESPONSE: await self.response.send(end_stream=True) except CancelledError: # Write an appropriate response before exiting e = self.exception or ServiceUnavailable("Cancelled") self.exception = None self.keep_alive = False await self.error_response(e) except Exception as e: # Write an error response await self.error_response(e) # Try to consume any remaining request body if self.request_body: if self.response and 200 <= self.response.status < 300: logger.error(f"{self.request} body not consumed.") try: async for _ in self: pass except PayloadTooLarge: # We won't read the body and that may cause httpx and # tests to fail. This little delay allows clients to push # a small request into network buffers before we close the # socket, so that they are then able to read the response. await sleep(0.001) self.keep_alive = False # Exit and disconnect if no more requests can be taken if self.stage is not Stage.IDLE or not self.keep_alive: break # Wait for next request if not self.recv_buffer: await self._receive_more()
def response_timeout_callback(self): # Check if elapsed time since response was initiated exceeds our # configured maximum request timeout value time_elapsed = current_time - self._last_request_time if time_elapsed < self.response_timeout: time_left = self.response_timeout - time_elapsed self._response_timeout_handler = (self.loop.call_later( time_left, self.response_timeout_callback)) else: try: raise ServiceUnavailable('Response Timeout') except ServiceUnavailable as exception: self.write_error(exception)
def response_timeout_callback(self): # Check if elapsed time since response was initiated exceeds our # configured maximum request timeout value time_elapsed = time() - self._last_request_time if time_elapsed < self.response_timeout: time_left = self.response_timeout - time_elapsed self._response_timeout_handler = self.loop.call_later( time_left, self.response_timeout_callback) else: if self._request_stream_task: self._request_stream_task.cancel() if self._request_handler_task: self._request_handler_task.cancel() self.write_error(ServiceUnavailable("Response Timeout"))
def _understand(self, text: str): """ Understand handler : client give a text query and we return a simplified version of the spaCy result document. :param text: the text query :return: simple json object with intents and entities. - intents: list of intents with its label and score, sorted by decreasing score; - entities: list of entities with its label and text (literal value). - verbs: list of the verbs in the sentence. - lemmas: list of lemmas in the sentence. - list of the tokens in the sentence. """ self._logger.debug(f"Trying to understand sentence : {text}") try: return json(self._request_service.understand(text)) except (ModelIsUpdatingException, ModelNeedAnUpdateException) as e: raise ServiceUnavailable(e)
async def get_features(self, db_name, table, geo_column, z, x, y): bounds = mercantile.bounds(x, y, z) if not valid_bounds(bounds): raise NotFound("Tile coordinates out of bounds") sql = """SELECT ROWID, *, AsText(Transform({geo_column}, 3857)) AS geom FROM {table} WHERE ROWID IN ({index_query})""".format( table=table, geo_column=geo_column, index_query=spatial_index_query(table, polygon_from_bounds(bounds)), ) try: res = await self.datasette.execute(db_name, sql) except InterruptedError: raise ServiceUnavailable("Query timed out") return [self.layer_from_result(table, res)]
async def callDelete(expectedStatus): try: async with request.app.ctx.usermgrd.delete( f'http://localhost/{user.name}') as resp: data = await resp.json() status = data['status'] if status == 'user_not_found': request.ctx.logger.warning(__name__ + '.delete.user_gone') return None elif status != expectedStatus: request.ctx.logger.error(__name__ + '.delete.usermgrd_error', reason=data['status']) raise ServerError('backend') return data except aiohttp.ClientConnectionError: request.ctx.logger.error(__name__ + '.delete.usermgrd_connect_failure') raise ServiceUnavailable('backend')
async def get(self, request, *args, station_no=None, **kwargs): '''Get cosmoz station calibrations.''' if station_no is None: raise RuntimeError("station_no is mandatory.") station_no = int(station_no) return_type = match_accept_mediatypes_to_provides( request, self.accept_types) format = request.args.getlist('format', None) if not format: format = request.args.getlist('_format', None) if format: format = next(iter(format)) if format in self.accept_types: return_type = format if return_type is None: return ServiceUnavailable("Please use a valid accept type.") if return_type == "application/json": property_filter = request.args.getlist('property_filter', None) if property_filter: property_filter = str(next(iter(property_filter))).split(',') property_filter = [p for p in property_filter if len(p)] else: # CSV and TXT get all properties, regardless of property_filter property_filter = "*" obs_params = { "property_filter": property_filter, } json_safe = 'orjson' if return_type == "application/json" else False jinja_safe = 'txt' if return_type == "text/plain" else False jinja_safe = 'csv' if return_type == "text/csv" else jinja_safe res = await get_station_calibration_mongo(station_no, obs_params, json_safe=json_safe, jinja_safe=jinja_safe) if return_type == "application/json": if use_body_bytes: resp = HTTPResponse(None, status=200, content_type=return_type, body_bytes=fast_dumps( res, option=orjson_option)) else: resp = HTTPResponse(fast_dumps(res, option=orjson_option), status=200, content_type=return_type) return resp headers = {'Content-Type': return_type} jinja2 = get_jinja2_for_api(self.api) if return_type == "text/csv": template = 'site_data_cal_csv.html' elif return_type == "text/plain": template = 'site_data_cal_txt.html' else: raise RuntimeError( "Cannot determine template name to use for response type.") if PY_36: return await jinja2.render_async(template, request, headers=headers, **res) else: return jinja2.render(template, request, headers=headers, **res)
async def get(self, _: Request, model_id: str): if self._spacy_manager.is_updating: raise ServiceUnavailable( message="A train is in progress. Wait some minutes.") return response.text("The model should work properly", status=200)
async def get_state_handler( request: Request, ip_address: str, phone_id: str, device_id: str, device_password: str, ) -> HTTPResponse: """Use for handling requests to /switcher/get_state. Args: request: ``sanic``'s request object. ip_address: the local ip address. phone_id: the extracted phone id. device_id: the extracted device id. device_password: the extracted device password. Raises: sanic.exceptions.ServerError: when encounterd any error. Returns: Json object represnting the current state of the device. More information is available in the ``Usage`` section. Note: Accepts arguments as json body or query parameters. """ try: async with SwitcherV2Api( get_running_loop(), ip_address, phone_id, device_id, device_password, ) as swapi: response = await swapi.get_state() if not response: raise ServiceUnavailable("Failed to get response from api.", 503) await response.init_future state_response = response.init_future.result() if (state_response and state_response.successful and state_response.msg_type == messages.ResponseMessageType.STATE): return json({ consts.KEY_SUCCESSFUL: state_response.successful, consts.KEY_STATE: state_response.state, consts.KEY_TIME_LEFT: state_response.time_left, consts.KEY_TIME_ON: state_response.time_on, consts.KEY_AUTO_OFF: state_response.auto_off, consts.KEY_POWER_CONSUMPTION: state_response.power, consts.KEY_ELECTRIC_CURRENT: state_response.current, }) return json({ consts.KEY_SUCCESSFUL: False, consts.KEY_MESSAGE: "Failed retrieving the device's state.", }) except ExceptionSet as exc: raise ServerError("Failed to get the device state.", 500) from exc
async def http1(self): """ HTTP 1.1 connection handler """ # Handle requests while the connection stays reusable while self.keep_alive and self.stage is Stage.IDLE: self.init_for_request() # Wait for incoming bytes (in IDLE stage) if not self.recv_buffer: await self._receive_more() self.stage = Stage.REQUEST try: # Receive and handle a request self.response_func = self.http1_response_header await self.http1_request_header() self.stage = Stage.HANDLER self.request.conn_info = self.protocol.conn_info await self.protocol.request_handler(self.request) # Handler finished, response should've been sent if self.stage is Stage.HANDLER and not self.upgrade_websocket: raise ServerError("Handler produced no response") if self.stage is Stage.RESPONSE: await self.response.send(end_stream=True) except CancelledError: # Write an appropriate response before exiting if not self.protocol.transport: logger.info( f"Request: {self.request.method} {self.request.url} " "stopped. Transport is closed.") return e = self.exception or ServiceUnavailable("Cancelled") self.exception = None self.keep_alive = False await self.error_response(e) except Exception as e: # Write an error response await self.error_response(e) # Try to consume any remaining request body if self.request_body: if self.response and 200 <= self.response.status < 300: error_logger.error(f"{self.request} body not consumed.") # Limit the size because the handler may have set it infinite self.request_max_size = min(self.request_max_size, self.protocol.request_max_size) try: async for _ in self: pass except PayloadTooLarge: # We won't read the body and that may cause httpx and # tests to fail. This little delay allows clients to push # a small request into network buffers before we close the # socket, so that they are then able to read the response. await sleep(0.001) self.keep_alive = False # Clean up to free memory and for the next request if self.request: self.request.stream = None if self.response: self.response.stream = None
async def http_503_error_handler(request, exception): raise ServiceUnavailable(str(exception))
def _request(request): raise ServiceUnavailable(message="Service unavailable")