def create_app(name=__name__, debug=False, worker_mode=False, testing_mode=False, avoid_context=False, enable_security=True, skip_endpoint_mapping=False, **kwargs): """ Create the server istance for Flask application """ ################################################# # Flask app instance ################################################# from .confs import config microservice = Flask(name, **kwargs) ############################## # @microservice.before_first_request # def first(): # print("BEFORE THE VERY FIRST REQUEST", g) # @microservice.before_request # def before(): # print("BEFORE EVERY REQUEST...") # @microservice.after_request # def after(response): # print("AFTER EVERY REQUEST...") # return response ############################## # Disable security if launching celery workers if worker_mode: enable_security = False # Set app internal testing mode if create_app received the parameter if testing_mode: microservice.config['TESTING'] = testing_mode ############################## # Flask configuration from config file microservice.config.from_object(config) if ENVVAR_DEBUG is not None: try: tmp = int(ENVVAR_DEBUG) == 1 except: tmp = str(ENVVAR_DEBUG).lower() == 'true' debug = tmp # bool(tmp) microservice.config['DEBUG'] = debug # Set the new level of debugging logger = get_logger(__name__, debug) logger.info("FLASKING! Created application") ############################## if PRODUCTION: logger.info("Production server ON") ## // TO FIX or CHECK # # Check and use a random file a secret key. # install_secret_key(microservice) # probably useless # # http://stackoverflow.com/a/26636880/2114395 # microservice.config.update( # dict(PREFERRED_URL_SCHEME = 'https') # ) # # To enable exceptions printing inside uWSGI # # http://stackoverflow.com/a/17839750/2114395 # from werkzeug.debug import DebuggedApplication # app.wsgi_app = DebuggedApplication(app.wsgi_app, True) ################################################# # Other components ################################################# ############################## # Cors from .cors import cors cors.init_app(microservice) logger.info("FLASKING! Injected CORS") ############################## # DATABASE/SERVICEs CHECKS from .resources.services.detect import services as internal_services for service, myclass in internal_services.items(): logger.info("Available service %s" % service) myclass(check_connection=True, app=microservice) ############################## # Enabling our internal Flask customized response from .response import InternalResponse microservice.response_class = InternalResponse ############################## # Flask security if enable_security: # Dynamically load the authentication service meta = Meta() module_base = __package__ + ".resources.services.authentication" auth_service = os.environ.get('BACKEND_AUTH_SERVICE', '') module_name = module_base + '.' + auth_service logger.debug("Trying to load the module %s" % module_name) module = meta.get_module_from_string(module_name) init_auth = create_auth_instance( module, internal_services, microservice) # Global namespace inside the Flask server @microservice.before_request def enable_authentication_per_request(): """ Save auth object """ # Authentication the right (per-instance) way custom_auth = create_auth_instance( module, internal_services, microservice) # Save globally across the code g._custom_auth = custom_auth # OLD BAD # def enable_global_authentication(): # """ Save auth object """ # g._custom_auth = custom_auth # Enabling also OAUTH library from .oauth import oauth oauth.init_app(microservice) logger.info("FLASKING! Injected security internal module") if not worker_mode: # Global namespace inside the Flask server @microservice.before_request def enable_global_services(): """ Save all databases/services """ g._services = internal_services ############################## # Restful plugin if not skip_endpoint_mapping: from .rest import Api, EndpointsFarmer, create_endpoints # Defining AUTOMATIC Resources current_endpoints = \ create_endpoints(EndpointsFarmer(Api), enable_security, debug) # Restful init of the app current_endpoints.rest_api.init_app(microservice) ############################## # Init objects inside the app context if not avoid_context: with microservice.app_context(): # Set global objects for celery workers if worker_mode: from commons.globals import mem mem.services = internal_services # Note: # Databases are already initialized inside the instances farm # Outside of the context # p.s. search inside this file for 'myclass(' # Init users/roles for Security if enable_security: # custom_auth.setup_secret(microservice.config['SECRET_KEY']) # custom_auth.init_users_and_roles() init_auth.init_users_and_roles() # Allow a custom method for mixed services init try: from .resources.custom import services as custom_services custom_services.init(internal_services, enable_security) except: logger.debug("No custom init available for mixed services") ############################## # Logging responses @microservice.after_request def log_response(response): data = handle_log_output(request.data) # Limit the parameters string size, sometimes it's too big for k in data: # print("K", k, "DATA", data) try: if not isinstance(data[k], str): continue if len(data[k]) > MAX_CHAR_LEN: data[k] = data[k][:MAX_CHAR_LEN] + "..." except IndexError: pass logger.info("{} {} {} {}".format( request.method, request.url, data, response)) return response ############################## # Enabling user callbacks after a request @microservice.after_request def call_after_request_callbacks(response): for callback in getattr(g, 'after_request_callbacks', ()): callback(response) return response ############################## # App is ready return microservice
def single_rest(self, config_file): meta = Meta() resources = [] sections = {} if not os.path.exists(config_file): logger.warning("File '%s' does not exist! Skipping." % config_file) return resources ######################### # Read the configuration inside this init file # JSON CASE try: sections = self.read_complex_config(config_file) except: # json.commentjson.JSONLibraryException: logger.critical("Format error!\n" + "'%s' file is not in JSON format" % config_file) exit(1) if 'apis' not in sections: logger.critical( "Section 'apis' not found in '%s' file" % config_file ) exit(1) ######################### # Use sections found for section, items in iteritems(sections['apis']): logger.debug("Configuration read: {Section: " + section + "}") module = meta.get_module_from_string( __package__ + '.resources.custom.' + section) # Skip what you cannot use if module is None: logger.warning("Could not find module '%s'..." % section) continue for classname, endpoints in iteritems(items): myclass = meta.get_class_from_string(classname, module) # Again skip if myclass is None: continue else: logger.debug("REST! Found resource: " + section + '.' + classname) # Get the best endpoint comparing inside against configuration instance = myclass() oldendpoint, endkey, endtype = instance.get_endpoint() if len(endpoints) < 1: endpoints = [oldendpoint] endpoint_id = None if endkey is not None and endtype is not None: endpoint_id = endtype + ':' + endkey resources.append((myclass, instance, endpoints, endpoint_id)) return resources