def response(self, request, exception): """Fetches and executes an exception handler and returns a response object :param request: Request :param exception: Exception to handle :return: Response object """ handler = self.lookup(exception) response = None try: if handler: response = handler(request=request, exception=exception) if response is None: response = self.default(request=request, exception=exception) except Exception: self.log(format_exc()) if self.debug: url = getattr(request, 'url', 'unknown') response_message = ( 'Exception raised in exception handler "{}" ' 'for uri: "{}"\n{}').format( handler.__name__, url, format_exc()) log.error(response_message) return text(response_message, 500) else: return text('An error occurred while handling an error', 500) return response
def authenticate_request(request: Request): global AUTH auth = request.headers.get("authorization") if auth: # Dummy auth check. We can have anything here and it's fine. if AUTH not in auth: return text("Unauthorized", status=401) else: return text("Unauthorized", status=401)
async def error_handler(request, exception): if request.method in ["HEAD", "PATCH", "PUT", "DELETE"]: return text( "", exception.status_code, headers=exception.headers ) else: return self.app.error_handler.default(request, exception)
def test_composition_view_runs_methods_as_expected(app, method): view = CompositionView() def first(request): assert request.stream is None return text("first method") view.add(["GET", "POST", "PUT"], first) view.add(["DELETE", "PATCH"], lambda x: text("second method")) app.add_route(view, "/") assert app.is_request_stream is False if method in ["GET", "POST", "PUT"]: request, response = getattr(app.test_client, method.lower())("/") assert response.text == "first method" response = view(request) assert response.body.decode() == "first method" if method in ["DELETE", "PATCH"]: request, response = getattr(app.test_client, method.lower())("/") assert response.text == "second method" response = view(request) assert response.body.decode() == "second method"
async def handle_request(request): urls = request.args.getlist('url') callback = request.args.get('callback') if urls: if len(urls) > 10: return response.json([{ 'ok': False, 'error': 'Max 10 URLs allowed' }], status=400) async with aiohttp.ClientSession() as session: head_infos = await asyncio.gather(*[ head(session, url) for url in urls ]) if callback and is_valid_callback(callback): return response.text( '{}({})'.format(callback, json.dumps(head_infos, indent=2)), content_type='application/javascript', headers={'Access-Control-Allow-Origin': '*'}, ) else: return response.json( head_infos, headers={'Access-Control-Allow-Origin': '*'}, ) else: return response.html(INDEX)
def write_response(self, response): if isinstance(response, str): response = text(response) self.transport.write( response.output(self.request.version) ) self.transport.close()
def handler(request): response = text("OK") response.cookies["test"] = "at you" response.cookies["test"]["httponly"] = True response.cookies["test"]["expires"] = datetime.now() + timedelta( seconds=10 ) return response
async def post_handler(request): result = '' while True: body = await request.stream.get() if body is None: break result += body.decode('utf-8') return text(result)
async def delete_account(req, clientid, token, jwt): async with shared.postgres.transaction(): stmt = await shared.postgres.prepare("DELETE FROM tb_users WHERE userid = $1") stmt.fetchv(clientid) await shared.redis.sadd("removed-id", clientid) return text("ok")
async def post_handler(request): assert isinstance(request.stream, asyncio.Queue) result = '' while True: body = await request.stream.get() if body is None: break result += body.decode('utf-8') return text(result)
async def health(request): """ returns the current health state of the system """ duration = time.time() - LAST_CALL_ROUTE_SERVICES if duration > settings.args.hangup_detection: msg = "system hang-up detected, it's been {} seconds since start of "\ "route_services".format(int(duration)) raise sanic.exceptions.ServerError(msg) return text("OK")
async def post_handler(request): assert isinstance(request.stream, StreamBuffer) result = "" while True: body = await request.stream.read() if body is None: break result += body.decode("utf-8") return text(result)
async def save(request): app = request.app artwork = request.files.getlist("artwork", []) artwork = [Artwork(f.name, f.type, f.body, None) for f in artwork] app.processor.cache_art(artwork) data = json.loads(request.form.get("data")) app.processor.save_all(data["tracks"], data["options"]) return response.text("")
async def update_my_account(req, jwt): allowed_fields = {"nickname", "email"} fields = allowed_fields & req.json.keys() if not fields: logging.warning(f"Unknown fields: {req.json.keys()}") raise InvalidUsage(f"Autorized fields are {allowed_fields}") async with shared.postgres.transaction(): sets = ", ".join([f"{field} = ${idx+2}" for idx, field in enumerate(fields)]) stmt = await shared.postgres.prepare(f"UPDATE tb_users SET {sets} WHERE userid = $1") await stmt.fetch(jwt["id"], *map(lambda field: req.json[field], fields)) return text("ok")
async def update_account(req, clientid, token, jwt): allowed_fields = {"nickname", "email", "password", "is_verfied", "is_admin"} fields = allowed_fields & req.json.keys() if not fields: logging.warning(f"Unknown fields: {req.json.keys()}") raise InvalidUsage(f"Autorized fields are {allowed_fields}") async with shared.postgres.transaction(): sets = " ".join([f"SET {field} = ${idx+2}" for idx, field in enumerate(fields)]) stmt = await shared.postgres.prepare(f"UPDATE FROM tb_users {sets} WHERE userid = $1") await stmt.fetch(clientid, *map(lambda field: req.json[field], fields)) return text("ok")
def test_composition_view_rejects_invalid_methods(app, method): view = CompositionView() view.add(["GET", "POST", "PUT"], lambda x: text("first method")) app.add_route(view, "/") if method in ["GET", "POST", "PUT"]: request, response = getattr(app.test_client, method.lower())("/") assert response.status == 200 assert response.text == "first method" if method in ["DELETE", "PATCH"]: request, response = getattr(app.test_client, method.lower())("/") assert response.status == 405
def response(self, request, exception): """Fetches and executes an exception handler and returns a response object :param request: Instance of :class:`sanic.request.Request` :param exception: Exception to handle :type request: :class:`sanic.request.Request` :type exception: :class:`sanic.exceptions.SanicException` or :class:`Exception` :return: Wrap the return value obtained from :func:`default` or registered handler for that type of exception. """ handler = self.lookup(exception) response = None try: if handler: response = handler(request, exception) if response is None: response = self.default(request, exception) except Exception: self.log(format_exc()) try: url = repr(request.url) except AttributeError: url = "unknown" response_message = ( "Exception raised in exception handler " '"%s" for uri: %s' ) logger.exception(response_message, handler.__name__, url) if self.debug: return text(response_message % (handler.__name__, url), 500) else: return text("An error occurred while handling an error", 500) return response
async def validate(req, clientid, token): if not (await shared.redis.exists(f"users:{clientid}:validation_token")): logger.log(45, f"No validation token available for user {clientid} (IP: {req.ip})") raise Forbidden("No validation token available for this account") validation_token = await (shared.redis.get(f"users:{clientid}:validation_token")) if not compare_digest(token.encode(), validation_token): logger.log(45, f"Wrong validation token for user {clientid} (IP: {req.ip})") raise Forbidden("Wrong validation token") async with shared.postgres.transaction(): stmt = await shared.postgres.prepare("SELECT set_user_verified($1);") await stmt.fetch(clientid) return text("ok")
async def reset(req, clientid): if not (await shared.redis.exists(f"users:{clientid}:reset_token")): logger.log(45, f"No reset token available for user {clientid} (IP: {req.ip})") raise Forbidden("No reset token available for this account") reset_token = await (shared.redis.get(f"users:{clientid}:reset_token")) if not compare_digest(req.json["token"].encode(), reset_token): logger.log(45, f"Wrong reset token for user {clientid} (IP: {req.ip})") raise Forbidden("Wrong reset token") async with shared.postgres.transaction(): stmt = await shared.postgres.prepare("UPDATE tb_users SET password = $1 WHERE userid = $2") await stmt.fetch(bcrypt.hashpw(req.json["password"].encode(), bcrypt.gensalt()), clientid) return text("ok")
def test_composition_view_rejects_invalid_methods(method): app = Sanic('test_composition_view') view = CompositionView() view.add(['GET', 'POST', 'PUT'], lambda x: text('first method')) app.add_route(view, '/') if method in ['GET', 'POST', 'PUT']: request, response = getattr(app.test_client, method.lower())('/') assert response.status == 200 assert response.text == 'first method' if method in ['DELETE', 'PATCH']: request, response = getattr(app.test_client, method.lower())('/') assert response.status == 405
def default(self, request, exception): self.log(format_exc()) if issubclass(type(exception), SanicException): return text( 'Error: {}'.format(exception), status=getattr(exception, 'status_code', 500), headers=getattr(exception, 'headers', dict()) ) elif self.debug: html_output = self._render_traceback_html(exception, request) response_message = ('Exception occurred while handling uri: ' '"%s"\n%s') logger.error(response_message, request.url, format_exc()) return html(html_output, status=500) else: return html(INTERNAL_SERVER_ERROR_HTML, status=500)
def test_composition_view_runs_methods_as_expected(method): app = Sanic('test_composition_view') view = CompositionView() def first(request): assert request.stream is None return text('first method') view.add(['GET', 'POST', 'PUT'], first) view.add(['DELETE', 'PATCH'], lambda x: text('second method')) app.add_route(view, '/') assert app.is_request_stream is False if method in ['GET', 'POST', 'PUT']: request, response = getattr(app.test_client, method.lower())('/') assert response.text == 'first method' if method in ['DELETE', 'PATCH']: request, response = getattr(app.test_client, method.lower())('/') assert response.text == 'second method'
def default(self, request, exception): """ Provide a default behavior for the objects of :class:`ErrorHandler`. If a developer chooses to extent the :class:`ErrorHandler` they can provide a custom implementation for this method to behave in a way they see fit. :param request: Incoming request :param exception: Exception object :type request: :class:`sanic.request.Request` :type exception: :class:`sanic.exceptions.SanicException` or :class:`Exception` :return: """ self.log(format_exc()) try: url = repr(request.url) except AttributeError: url = "unknown" response_message = "Exception occurred while handling uri: %s" logger.exception(response_message, url) if issubclass(type(exception), SanicException): return text( "Error: {}".format(exception), status=getattr(exception, "status_code", 500), headers=getattr(exception, "headers", dict()), ) elif self.debug: html_output = self._render_traceback_html(exception, request) return html(html_output, status=500) else: return html(INTERNAL_SERVER_ERROR_HTML, status=500)
async def handler(request): headers = {"spam": "great"} return text('Hello', headers=headers)
def one(request): return text("one")
async def default_handler(request): return text("OK")
def digest_auth_route(request): return text(f"digest_auth:{digest_auth.username(request)}")
def ignore_404s(request, exception): return text("Yep, I totally found the page: {}".format(request.url))
def index(request): return text("hello world")
async def server_error_handler(request, exception): return text('Oops, Sanic Server Error! Please contact the blog owner', status=500)
async def ignore_404s(request, exception): return text("Oops, That page couldn't found.")
def get(self, request): return text("I am get method")
def handler_exception(request, exception): return text('Internal Server Error.', 500)
async def handler(request): headers = {"answer": 42} return text('Hello', headers=headers)
async def handler(request): return text('OK')
def post_handler(request): return text("OK")
def handler_exception(request, exception): return text('Payload Too Large from error_handler.', 413)
def handler_exception(request, exception): return text("OK")
def index(request): return text("index")
def default_route(request): if request.headers.get("accepts") == "application/json": return json({"test": "value"}) else: return text("value")
def f1(request): return text("f1")
def handler(request): return text("{}".format(request.ip))
def third(request): return text("third")
async def handler(request): return text(request.remote_addr)
def second(request): return text("second")
async def handler(request): return text(request.content_type)
def get_handler(request): return text("OK")
async def handler(request): return text('Hello')
def handler_500_error(request): abort(500) return text("OK")
def handler_4(request): foo = bar # noqa -- F821 undefined name 'bar' is done to throw exception return text(foo)
async def reset_count(req): global request_count, compute_time request_count = compute_time = 0 return text('Instance count reset')
def handler_test(request): return text("Test")
def handler(request): return text("OK")
async def reset_shared_count(req): await redis.set(shared_counter, 0) return text('Shared count reset')
def exception_list(request, exception): return text("ok")
async def compute_for_random_interval(a,b): return text(compute_for_time(randint(a,b)))
def handler_6(request, arg): try: foo = 1 / arg except Exception as e: raise e from ValueError("{}".format(arg)) return text(foo)
async def get_name(req): global request_count request_count = request_count + 1 if redis: await redis.incr(shared_counter) return text(gethostname())
async def robots(request): from sanic.response import text return text('User-agent: * \nCrawl-delay: 10 \nDisallow: /admin')
def handler(request): return text("Hello")