Spaces:
Paused
Paused
| import os | |
| if os.environ.get("DEBUG", "false").lower() != "true": | |
| from gevent import monkey | |
| monkey.patch_all() | |
| import grpc.experimental.gevent | |
| grpc.experimental.gevent.init_gevent() | |
| import json | |
| from flask import Flask, Response, request | |
| from flask_cors import CORS | |
| from werkzeug.exceptions import Unauthorized | |
| import contexts | |
| from commands import register_commands | |
| from configs import dify_config | |
| from extensions import ( | |
| ext_celery, | |
| ext_code_based_extension, | |
| ext_compress, | |
| ext_database, | |
| ext_hosting_provider, | |
| ext_logging, | |
| ext_login, | |
| ext_mail, | |
| ext_migrate, | |
| ext_proxy_fix, | |
| ext_redis, | |
| ext_sentry, | |
| ext_storage, | |
| ) | |
| from extensions.ext_database import db | |
| from extensions.ext_login import login_manager | |
| from libs.passport import PassportService | |
| from services.account_service import AccountService | |
| from flask_migrate import Migrate | |
| class DifyApp(Flask): | |
| pass | |
| # ---------------------------- | |
| # Application Factory Function | |
| # ---------------------------- | |
| def create_flask_app_with_configs() -> Flask: | |
| """ | |
| create a raw flask app | |
| with configs loaded from .env file | |
| """ | |
| dify_app = DifyApp(__name__) | |
| dify_app.config.from_mapping(dify_config.model_dump()) | |
| # populate configs into system environment variables | |
| for key, value in dify_app.config.items(): | |
| if isinstance(value, str): | |
| os.environ[key] = value | |
| elif isinstance(value, int | float | bool): | |
| os.environ[key] = str(value) | |
| elif value is None: | |
| os.environ[key] = "" | |
| return dify_app | |
| def create_app() -> Flask: | |
| app = create_flask_app_with_configs() | |
| app.secret_key = dify_config.SECRET_KEY | |
| initialize_extensions(app) | |
| register_blueprints(app) | |
| register_commands(app) | |
| return app | |
| def initialize_extensions(app): | |
| # Since the application instance is now created, pass it to each Flask | |
| # extension instance to bind it to the Flask application instance (app) | |
| ext_logging.init_app(app) | |
| ext_compress.init_app(app) | |
| ext_code_based_extension.init() | |
| ext_database.init_app(app) | |
| ext_migrate.init(app, ext_database.db) | |
| ext_redis.init_app(app) | |
| ext_storage.init_app(app) | |
| ext_celery.init_app(app) | |
| ext_login.init_app(app) | |
| ext_mail.init_app(app) | |
| ext_hosting_provider.init_app(app) | |
| ext_sentry.init_app(app) | |
| ext_proxy_fix.init_app(app) | |
| # Flask-Login configuration | |
| def load_user_from_request(request_from_flask_login): | |
| """Load user based on the request.""" | |
| if request.blueprint not in {"console", "inner_api"}: | |
| return None | |
| # Check if the user_id contains a dot, indicating the old format | |
| auth_header = request.headers.get("Authorization", "") | |
| if not auth_header: | |
| auth_token = request.args.get("_token") | |
| if not auth_token: | |
| raise Unauthorized("Invalid Authorization token.") | |
| else: | |
| if " " not in auth_header: | |
| raise Unauthorized("Invalid Authorization header format. Expected 'Bearer <api-key>' format.") | |
| auth_scheme, auth_token = auth_header.split(None, 1) | |
| auth_scheme = auth_scheme.lower() | |
| if auth_scheme != "bearer": | |
| raise Unauthorized("Invalid Authorization header format. Expected 'Bearer <api-key>' format.") | |
| decoded = PassportService().verify(auth_token) | |
| user_id = decoded.get("user_id") | |
| logged_in_account = AccountService.load_logged_in_account(account_id=user_id) | |
| if logged_in_account: | |
| contexts.tenant_id.set(logged_in_account.current_tenant_id) | |
| return logged_in_account | |
| def unauthorized_handler(): | |
| """Handle unauthorized requests.""" | |
| return Response( | |
| json.dumps({"code": "unauthorized", "message": "Unauthorized."}), | |
| status=401, | |
| content_type="application/json", | |
| ) | |
| # register blueprint routers | |
| def register_blueprints(app): | |
| from controllers.console import bp as console_app_bp | |
| from controllers.files import bp as files_bp | |
| from controllers.inner_api import bp as inner_api_bp | |
| from controllers.service_api import bp as service_api_bp | |
| from controllers.web import bp as web_bp | |
| CORS( | |
| service_api_bp, | |
| allow_headers=["Content-Type", "Authorization", "X-App-Code"], | |
| methods=["GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH"], | |
| ) | |
| app.register_blueprint(service_api_bp) | |
| CORS( | |
| web_bp, | |
| resources={r"/*": {"origins": dify_config.WEB_API_CORS_ALLOW_ORIGINS}}, | |
| supports_credentials=True, | |
| allow_headers=["Content-Type", "Authorization", "X-App-Code"], | |
| methods=["GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH"], | |
| expose_headers=["X-Version", "X-Env"], | |
| ) | |
| app.register_blueprint(web_bp) | |
| CORS( | |
| console_app_bp, | |
| resources={r"/*": {"origins": dify_config.CONSOLE_CORS_ALLOW_ORIGINS}}, | |
| supports_credentials=True, | |
| allow_headers=["Content-Type", "Authorization"], | |
| methods=["GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH"], | |
| expose_headers=["X-Version", "X-Env"], | |
| ) | |
| app.register_blueprint(console_app_bp) | |
| CORS(files_bp, allow_headers=["Content-Type"], methods=["GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH"]) | |
| app.register_blueprint(files_bp) | |
| app.register_blueprint(inner_api_bp) | |