mirror of
https://github.com/langgenius/dify.git
synced 2026-05-09 12:59:18 +08:00
feat(api): scaffold /openapi/v1 blueprint (Phase A.1)
New Flask blueprint at /openapi/v1/ that will host user-scoped programmatic endpoints (device flow, identity, sessions, workspaces). Ships only a smoke route GET /openapi/v1/_health for now; subsequent phases lift handlers in from service_api, console, and the orphan oauth_device_sso.py. CORS is intentionally omitted here and configured in step A.5 once the allowlist envvar lands. Plan: docs/superpowers/plans/2026-04-26-openapi-migration.md (in difyctl repo).
This commit is contained in:
parent
813da349ec
commit
f5f224f49d
23
api/controllers/openapi/__init__.py
Normal file
23
api/controllers/openapi/__init__.py
Normal file
@ -0,0 +1,23 @@
|
||||
from flask import Blueprint
|
||||
from flask_restx import Namespace
|
||||
|
||||
from libs.external_api import ExternalApi
|
||||
|
||||
bp = Blueprint("openapi", __name__, url_prefix="/openapi/v1")
|
||||
|
||||
api = ExternalApi(
|
||||
bp,
|
||||
version="1.0",
|
||||
title="OpenAPI",
|
||||
description="User-scoped programmatic API (bearer auth)",
|
||||
)
|
||||
|
||||
openapi_ns = Namespace("openapi", description="User-scoped operations", path="/")
|
||||
|
||||
from . import index
|
||||
|
||||
__all__ = [
|
||||
"index",
|
||||
]
|
||||
|
||||
api.add_namespace(openapi_ns)
|
||||
9
api/controllers/openapi/index.py
Normal file
9
api/controllers/openapi/index.py
Normal file
@ -0,0 +1,9 @@
|
||||
from flask_restx import Resource
|
||||
|
||||
from controllers.openapi import openapi_ns
|
||||
|
||||
|
||||
@openapi_ns.route("/_health")
|
||||
class HealthApi(Resource):
|
||||
def get(self):
|
||||
return {"ok": True}
|
||||
@ -29,6 +29,7 @@ def init_app(app: DifyApp):
|
||||
from controllers.files import bp as files_bp
|
||||
from controllers.inner_api import bp as inner_api_bp
|
||||
from controllers.mcp import bp as mcp_bp
|
||||
from controllers.openapi import bp as openapi_bp
|
||||
from controllers.service_api import bp as service_api_bp
|
||||
from controllers.trigger import bp as trigger_bp
|
||||
from controllers.web import bp as web_bp
|
||||
@ -41,6 +42,9 @@ def init_app(app: DifyApp):
|
||||
)
|
||||
app.register_blueprint(service_api_bp)
|
||||
|
||||
# User-scoped programmatic API. CORS configured in Phase A step 5.
|
||||
app.register_blueprint(openapi_bp)
|
||||
|
||||
_apply_cors_once(
|
||||
web_bp,
|
||||
resources={
|
||||
|
||||
33
api/tests/unit_tests/controllers/openapi/test_health.py
Normal file
33
api/tests/unit_tests/controllers/openapi/test_health.py
Normal file
@ -0,0 +1,33 @@
|
||||
import builtins
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
from flask.views import MethodView
|
||||
|
||||
from controllers.openapi import bp as openapi_bp
|
||||
|
||||
if not hasattr(builtins, "MethodView"):
|
||||
builtins.MethodView = MethodView # type: ignore[attr-defined]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app() -> Flask:
|
||||
app = Flask(__name__)
|
||||
app.config["TESTING"] = True
|
||||
app.register_blueprint(openapi_bp)
|
||||
return app
|
||||
|
||||
|
||||
def test_health_returns_ok(app: Flask):
|
||||
client = app.test_client()
|
||||
response = client.get("/openapi/v1/_health")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.get_json() == {"ok": True}
|
||||
|
||||
|
||||
def test_health_path_is_under_openapi_v1_prefix(app: Flask):
|
||||
client = app.test_client()
|
||||
assert client.get("/_health").status_code == 404
|
||||
assert client.get("/v1/_health").status_code == 404
|
||||
assert client.get("/openapi/v1/_health").status_code == 200
|
||||
Loading…
Reference in New Issue
Block a user