|
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 |
|
|
|
|
|
class DifyApp(Flask): |
|
pass |
|
|
|
|
|
|
|
|
|
|
|
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()) |
|
|
|
|
|
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): |
|
|
|
|
|
ext_logging.init_app(app) |
|
ext_compress.init_app(app) |
|
ext_code_based_extension.init() |
|
ext_database.init_app(app) |
|
ext_migrate.init(app, 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) |
|
|
|
|
|
|
|
@login_manager.request_loader |
|
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 |
|
|
|
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 |
|
|
|
|
|
@login_manager.unauthorized_handler |
|
def unauthorized_handler(): |
|
"""Handle unauthorized requests.""" |
|
return Response( |
|
json.dumps({"code": "unauthorized", "message": "Unauthorized."}), |
|
status=401, |
|
content_type="application/json", |
|
) |
|
|
|
|
|
|
|
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) |
|
|