예제 #1
0
async def get_handler(request: web.Request):
    try:
        admins = None
        if len(request.rel_url.query.keys()) == 0:
            admins = await Admin.get_all(DB.get(request, table))
        else:
            admins = []
            if 'id' in request.rel_url.query:
                admin_id = request.rel_url.query.get('id')
                Validate.validate_object_id(admin_id)
                admin = await Admin.get_by_id(admin_id, DB.get(request, table))
                if admin is not None:
                    admins.append(admin)
            elif 'email' in request.rel_url.query:
                admin_email = request.rel_url.query.get('email')
                admins = await Admin.get_by_email(admin_email,
                                                  DB.get(request, table))
            elif 'username' in request.rel_url.query:
                admin_username = request.rel_url.query.get('username')
                admins = await Admin.get_by_username(admin_username,
                                                     DB.get(request, table))
        return web.json_response({
            'data':
            DB.format_documents(Bson.to_json(admins)),
            'status_code':
            200
        })
    except Exception as err:
        return Error.handle(err)
예제 #2
0
async def get_handler(request: web.Request):
    try:
        if len(request.rel_url.query.keys()) == 0:
            services = await Service.get_all(DB.get(request, table))
            return web.json_response({
                'data':
                DB.format_documents(Bson.to_json(services)),
                'status_code':
                200
            })
        else:
            services = []
            if 'id' in request.rel_url.query:
                Validate.validate_object_id(request.rel_url.query.get('id'))
                service = await Service.get_by_id(
                    request.rel_url.query.get('id'), DB.get(request, table))
                if service is not None:
                    services.append(service)
            elif 'state' in request.rel_url.query:
                services = await Service.get_by_state(
                    request.rel_url.query.get('state'), DB.get(request, table))
            elif 'secure' in request.rel_url.query:
                services = await Service.get_by_secure(
                    bool(request.rel_url.query.get('secure')),
                    DB.get(request, table))
            return web.json_response({
                'data':
                DB.format_documents(Bson.to_json(services)),
                'status_code':
                200
            })
    except Exception as err:
        return Error.handle(err)
예제 #3
0
async def get_handler(request: web.Request):
    try:
        response = []
        if 'service_id' in request.rel_url.query:
            Validate.validate_object_id(request.rel_url.query['service_id'])
            service_id = request.rel_url.query['service_id']
            response = await RequestValidator.get_by_service_id(
                service_id, DB.get(request, table))
        elif 'id' in request.rel_url.query:
            Validate.validate_object_id(request.rel_url.query.get('id'))
            req_validator = await RequestValidator.get_by_id(
                request.rel_url.query.get('id'), DB.get(request, table))
            if req_validator is not None:
                response.append(req_validator)
        elif 'method' in request.rel_url.query:
            method = request.rel_url.query['method']
            response = await RequestValidator.get_by_method(
                method, DB.get(request, table))
        else:
            response = await RequestValidator.get_all(DB.get(request, table))
        return web.json_response(
            {
                'status_code': 200,
                'data': Bson.to_json(response)
            }, status=200)
    except Exception as err:
        return Error.handle(err)
예제 #4
0
async def proxy(request: web.Request, handler: web.RequestHandler):
    try:
        req_start_time = time()
        if pydash.starts_with(request.path_qs, '/raven'):
            return await handler(request)

        service = Regex.best_match(await Regex.get_matched_paths(request.path, DB.get(request, service_controller.table)))
        await handle_service(service, request.remote)

        rate_limiter_rules = await RateLimiter.get_rule_by_service_id(str(service['_id']), DB.get_redis(request))
        rate_limiter_rule = rate_limiter_rules[0] if rate_limiter_rules else None
        await handle_rate_limiter(request, str(service['_id']), rate_limiter_rule)

        breakers = await CircuitBreaker.get_by_service_id(str(service['_id']), DB.get(request, circuit_breaker_controller.table))
        breaker = breakers[0] if breakers else None

        request_validators = await RequestValidator.get_by_service_id(str(service['_id']), DB.get(request, request_validator_controller.table))
        request_validator = request_validators[0] if request_validators else None

        endpoint_cachers = not pydash.is_empty(service) and await EndpointCacher.get_by_service_id(str(service['_id']), DB.get_redis(request)) or None
        endpoint_cacher = endpoint_cachers[0] if endpoint_cachers else None

        await handle_request_validator(request_validator, json.loads(await request.text()), request.method)
        req, req_cache_hit = await handle_request(request, service, endpoint_cacher)

        checks = []

        if not pydash.is_empty(
                breaker) and breaker['status'] == CircuitBreakerStatus.ON.name:
            if req['status'] in breaker['status_codes']:
                checks.append(handle_circuit_breaker(
                    breaker, service, request, req))
            else:
                await CircuitBreaker.incr_count(str(breaker['_id']), DB.get_redis(request))

        queue_async_func.s({
            'func': 'Service.advance_target',
            'args': [str(service['_id']), f'mongo:{service_controller.table}'],
            'kwargs': {}
        }).apply_async()
        req_finish_time = time()
        req_elapsed_time = req_finish_time - req_start_time
        checks.append(handle_insights(request, req, str(
            service['_id']), req_elapsed_time, req_cache_hit))
        await Async.all(checks)

        return web.Response(
            body=Bytes.decode_bytes(
                req['body_bytes']),
            status=req['status'],
            content_type=req['content_type'],
            headers=CIMultiDict(
                pydash.omit(
                    req['headers'],
                    'Content-Type',
                    'Transfer-Encoding',
                    'Content-Encoding')))
    except Exception as err:
        return Error.handle(err)
예제 #5
0
async def handle_circuit_breaker(breaker: object, service: object, request: web.Request, req: object):
    if req['status'] in breaker['status_codes']:
        breaker_count = await CircuitBreaker.get_count(
            str(breaker['_id']),
            DB.get_redis(request)
        )
    if not breaker_count:
        await CircuitBreaker.set_count(
            str(breaker['_id']),
            0,
            breaker['period'],
            DB.get_redis(request)
        )
    else:
        failures_rate = breaker['tripped_count'] / int(breaker_count)
        if failures_rate >= (1 - breaker['threshold']):
            queued = await CircuitBreaker.get_queued(str(breaker['_id']), DB.get_redis(request))
            if not queued or queued is 'False':
                cooldown_eta = datetime.utcnow(
                ) + timedelta(seconds=breaker['cooldown'])
                queue_async_func.s({'func': 'Service.update',
                                    'args': [str(service['_id']),
                                             {'state': ServiceState.DOWN.name},
                                             f'mongo:{service_controller.table}'],
                                    'kwargs': {}}).apply_async()
                queue_async_func.s({
                    'func': 'CircuitBreaker.set_queued',
                    'args': [str(breaker['_id']), 'True', breaker['cooldown'], 'redis'],
                    'kwargs': {}
                }).apply_async()
                queue_async_func.s({'func': 'Service.update',
                                    'args': [str(service['_id']),
                                             {'state': ServiceState.UP.name},
                                             f'mongo:{service_controller.table}'],
                                    'kwargs': {}}).apply_async(eta=cooldown_eta)
                queue_async_func.s({
                    'func': 'CircuitBreaker.set_queued',
                    'args': [str(breaker['_id']), 'False', breaker['cooldown'], 'redis'],
                    'kwargs': {}
                }).apply_async(eta=cooldown_eta)
                queue_async_func.s({'func': 'CircuitBreaker.update',
                                    'args': [str(breaker['_id']),
                                             {'tripped_count': 0},
                                             f'mongo:{circuit_breaker_controller.table}'],
                                    'kwargs': {}}).apply_async(eta=cooldown_eta)
                events = await Event.get_by_circuit_breaker_id(str(breaker['_id']), DB.get(request, event_controller.table))
                for event in events:
                    queue_async_func.s({
                        'func': 'Event.handle_event',
                        'args': [Bson.to_json(event)],
                        'kwargs': {}
                    }).apply_async()
    await Async.all([
        CircuitBreaker.incr_tripped_count(str(breaker['_id']), DB.get(
            request, circuit_breaker_controller.table)),
        CircuitBreaker.incr_count(str(breaker['_id']), DB.get_redis(request))
    ])
예제 #6
0
async def post_handler(request: web.Request):
    try:
        body = json.loads(await request.text())
        Validate.validate_schema(body, insights_validator)
        await Insights.create(body, DB.get(request, table),
                              DB.get(request, controller.table))
        return web.json_response({
            'message': 'Insight created',
            'status_code': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #7
0
async def post_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        Validate.validate_schema(ctx, event_validator)
        await Event.create(ctx, DB.get(request, table),
                           DB.get(request, controller.table))
        return web.json_response({
            'message': 'Event created',
            'status_code': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #8
0
async def create_handler(request: web.Request):
    try:
        body = json.loads(await request.text())
        Validate.validate_schema(body, request_validator)
        await RequestValidator.create(request_validator.normalized(body),
                                      DB.get(request, table),
                                      DB.get(request, controller.table))
        return web.json_response({
            'message': 'Request validator created',
            'status_code': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #9
0
async def login_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        verified = await Admin.verify_password(ctx['username'],
                                               ctx['password'],
                                               DB.get(request, table))
        if not verified:
            raise Exception({'message': 'Unathorized', 'status_code': 401})
        admin = await Admin.get_by_username(ctx['username'],
                                            DB.get(request, table))
        sanitized_admin = pydash.omit(admin, 'password')
        return web.json_response(
            {'data': DB.format_document(Bson.to_json(sanitized_admin))})
    except Exception as err:
        return Error.handle(err)
예제 #10
0
async def get_handler(request: web.Request):
    try:
        circuit_breakers = None
        if len(request.rel_url.query.keys()) == 0:
            circuit_breakers = await CircuitBreaker.get_all(DB.get(request, table))
        else:
            circuit_breakers = []
            if 'id' in request.rel_url.query:
                Validate.validate_object_id(request.rel_url.query.get('id'))
                circuit_breaker = await CircuitBreaker.get_by_id(request.rel_url.query.get('id'), DB.get(request, table))
                if circuit_breaker is not None:
                    circuit_breakers.append(circuit_breaker)
            elif 'service_id' in request.rel_url.query:
                Validate.validate_object_id(
                    request.rel_url.query.get('service_id'))
                circuit_breakers = await CircuitBreaker.get_by_service_id(request.rel_url.query.get('service_id'), DB.get(request, table))
            elif 'status_code' in request.rel_url.query:
                circuit_breakers = await CircuitBreaker.get_by_status_code(int(request.rel_url.query.get('status_code')), DB.get(request, table))
            elif 'method' in request.rel_url.query:
                circuit_breakers = await CircuitBreaker.get_by_method(request.rel_url.query.get('method'), DB.get(request, table))
            elif 'threshold' in request.rel_url.query:
                circuit_breakers = await CircuitBreaker.get_by_threshold(float(request.rel_url.query.get('threshold')), DB.get(request, table))
        return web.json_response({
            'data': DB.format_documents(Bson.to_json(circuit_breakers)),
            'status_code': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #11
0
async def delete_handler(request: web.Request):
    try:
        Validate.validate_object_id(request.rel_url.query.get('id'))
        await Service.remove(request.rel_url.query.get('id'),
                             DB.get(request, table))
        return web.json_response({'message': 'service deleted'})
    except Exception as err:
        return Error.handle(err)
예제 #12
0
async def post_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        Validate.validate_schema(ctx, admin_validator)
        await Admin.create(ctx, DB.get(request, table))
        return web.json_response({
            'message': 'Admin created',
        })
    except Exception as err:
        return Error.handle(err)
예제 #13
0
async def post_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        Validate.validate_schema(ctx, circuit_breaker_validator)
        await CircuitBreaker.create(circuit_breaker_validator.normalized(ctx), DB.get(request, table), DB.get(request, controller.table))
        return web.json_response({
            'message': 'Circuit breaker created',
            'status_code': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #14
0
async def delete_handler(request: web.Request):
    try:
        id = request.rel_url.query.get('id')
        Validate.validate_object_id(id)
        await RequestValidator.delete(id, DB.get(request, table))
        return web.json_response({
            'message': 'request validator deleted',
            'statusCode': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #15
0
async def delete_handler(request: web.Request):
    try:
        service_id = request.rel_url.query.get('id')
        Validate.validate_object_id(service_id)
        await Insights.remove(service_id, DB.get(request, table))
        return web.json_response({
            'message': 'insight deleted',
            'status_code': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #16
0
async def post_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        Validate.validate_schema(ctx, service_validator)
        await Service.create(service_validator.normalized(ctx),
                             DB.get(request, table))
        return web.json_response({
            'message': 'service created',
        })
    except Exception as err:
        return Error.handle(err)
예제 #17
0
async def patch_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        circuit_breaker_id = request.rel_url.query['id']
        Validate.validate_schema(ctx, circuit_breaker_validator)
        Validate.validate_object_id(circuit_breaker_id)
        await CircuitBreaker.update(circuit_breaker_id, pydash.omit(ctx, 'id'), DB.get(request, table))
        return web.json_response({
            'message': 'Circuit breaker updated',
        })
    except Exception as err:
        return Error.handle(err)
예제 #18
0
async def patch_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        admin_id = request.rel_url.query['id']
        Validate.validate_schema(ctx, admin_validator)
        Validate.validate_object_id(admin_id)
        await Admin.update(admin_id, ctx, DB.get(request, table))
        return web.json_response({
            'message': 'Admin updated',
        })
    except Exception as err:
        return Error.handle(err)
예제 #19
0
async def patch_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        service_id = request.rel_url.query.get('id')
        Validate.validate_object_id(service_id)
        Validate.validate_schema(ctx, service_validator)
        await Service.update(service_id, ctx, DB.get(request, table))
        return web.json_response({
            'message': 'service updated',
        })
    except Exception as err:
        return Error.handle(err)
예제 #20
0
async def update_handler(request: web.Request):
    try:
        id = request.rel_url.query['id']
        body = json.loads(await request.text())
        Validate.validate_object_id(id)
        Validate.validate_schema(body, request_validator)
        await RequestValidator.update(id, body, DB.get(request, table))
        return web.json_response({
            'message': 'request validator updated',
            'status_code': 200
        })
    except Exception as err:
        return Error.handle(err)
예제 #21
0
async def patch_handler(request: web.Request):
    try:
        ctx = json.loads(await request.text())
        service_id = request.rel_url.query['id']
        Validate.validate_object_id(service_id)
        Validate.validate_schema(ctx, insights_validator)
        await Insights.update(service_id, pydash.omit(ctx, 'id'),
                              DB.get(request, table))
        return web.json_response({
            'message': 'insight updated',
        })
    except Exception as err:
        return Error.handle(err)
예제 #22
0
async def get_handler(request: web.Request):
    try:
        if len(request.rel_url.query.keys()) == 0:
            insights = await Insights.get_all(DB.get(request, table))
        else:
            insights = []
            if 'id' in request.rel_url.query:
                insight = await Insights.get_by_id(
                    request.rel_url.query.get('id'), DB.get(request, table))
                if insight is not None:
                    insights.append(insight)
            elif 'remote_ip' in request.rel_url.query:
                insights = await Insights.get_by_remote_ip(
                    request.rel_url.query.get('remote_ip'),
                    DB.get(request, table))
            elif 'status_code' in request.rel_url.query:
                insights = await Insights.get_by_status_code(
                    request.rel_url.query.get('status_code'),
                    DB.get(request, table))
            elif 'path' in request.rel_url.query:
                insights = await Insights.get_by_path(
                    request.rel_url.query.get('path'), DB.get(request, table))
            elif 'method' in request.rel_url.query:
                insights = await Insights.get_by_method(
                    request.rel_url.query.get('method'),
                    DB.get(request, table))
            elif 'service_id' in request.rel_url.query:
                insights = await Insights.get_by_service_id(
                    request.rel_url.query.get('service_id'),
                    DB.get(request, table))
            elif 'scheme' in request.rel_url.query:
                insights = await Insights.get_by_scheme(
                    request.rel_url.query.get('scheme'),
                    DB.get(request, table))
        return web.json_response({
            'data':
            DB.format_documents(Bson.to_json(insights)),
            'status_code':
            200
        })
    except Exception as err:
        return Error.handle(err)
예제 #23
0
async def auth_middleware(request: web.Request, handler: web.RequestHandler):
    try:
        if '/admin/login' not in request.path_qs:
            err = {'message': 'Unauthorized!', 'status_code': 401}
            token = request.headers.get(TOKEN_HEADER_KEY)

            if not token:
                raise Exception(err)

            token_context = Token.decode(token)
            admin = await Admin.get_by_id(token_context['_id'],
                                          DB.get(request))

            if not admin or 'token' not in admin or admin['token'] != token:
                raise Exception(err)

        return await handler(request)
    except Exception as err:
        return Error.handle(err)