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)
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)
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)
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)
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)) ])
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)