diff --git a/backend/app.py b/backend/app.py index 951a1f9..1ffda7a 100644 --- a/backend/app.py +++ b/backend/app.py @@ -4,24 +4,36 @@ import requests from flask import Flask, jsonify, request, abort from flask_cors import CORS +from flasgger import Swagger, swag_from from datetime import datetime, UTC from embedding_description import main as classify_description from embedding_url import main as classify_url from aurora_api import main as aurora_classify +from swagger_docs import ( + SWAGGER_TEMPLATE, + HELLO_DOC, + CLASSIFY_AURORA_DOC, + CLASSIFY_ST_DESCRIPTION_DOC, + CLASSIFY_ST_URL_DOC, + OSDG_API_DOC, +) app = Flask(__name__) CORS(app) +swagger = Swagger(app, template=SWAGGER_TEMPLATE) @app.route('/api/hello', methods=['GET']) +@swag_from(HELLO_DOC) def hello(): return jsonify({'message': 'Hello, World!'}) @app.route('/api/classify_aurora', methods=['POST']) +@swag_from(CLASSIFY_AURORA_DOC) def classify_aurora(): data = request.json projectName = data.get('projectName') @@ -70,6 +82,7 @@ def classify_aurora(): @app.route('/api/classify_st_description', methods=['POST']) +@swag_from(CLASSIFY_ST_DESCRIPTION_DOC) def classify_st_description(): data = request.json projectName = data.get('projectName') @@ -113,6 +126,7 @@ def classify_st_description(): @app.route('/api/classify_st_url', methods=['POST']) +@swag_from(CLASSIFY_ST_URL_DOC) def classify_st_url(): data = request.json projectName = data.get('projectName') @@ -163,6 +177,7 @@ def classify_st_url(): }), 200 @app.route("/api/osdg_api", methods=["POST"]) +@swag_from(OSDG_API_DOC) def osdg_external_api(): data = request.json projectName = data.get('projectName') diff --git a/backend/requirements.txt b/backend/requirements.txt index 4c8586c..e5c55b0 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -6,4 +6,5 @@ numpy accelerate flask flask-cors -Flask-UUID \ No newline at end of file +Flask-UUID +flasgger \ No newline at end of file diff --git a/backend/swagger_docs.py b/backend/swagger_docs.py new file mode 100644 index 0000000..6ca802c --- /dev/null +++ b/backend/swagger_docs.py @@ -0,0 +1,154 @@ +""" +Swagger/OpenAPI docs definitions for Flask routes. +Keeping specs here keeps app.py focused on request handling. +""" + +SWAGGER_TEMPLATE = { + "swagger": "2.0", + "info": { + "title": "UNSDG Classifier API", + "description": "API docs for SDG classification routes.", + "version": "1.0.0", + }, + "basePath": "/", + "schemes": ["http", "https"], +} + +HELLO_DOC = { + "tags": ["Health"], + "responses": { + 200: { + "description": "API is alive", + "schema": { + "type": "object", + "properties": { + "message": {"type": "string", "example": "Hello, World!"} + }, + }, + } + }, +} + +CLASSIFY_AURORA_DOC = { + "tags": ["Classification"], + "parameters": [ + { + "in": "body", + "name": "body", + "required": True, + "schema": { + "type": "object", + "required": ["projectDescription"], + "properties": { + "projectName": {"type": "string", "example": "My Project"}, + "projectUrl": { + "type": "string", + "example": "https://github.com/org/repo", + }, + "projectDescription": { + "type": "string", + "example": "AI tool for clean energy monitoring.", + }, + }, + }, + } + ], + "responses": { + 200: {"description": "SDG predictions"}, + 400: {"description": "Missing projectDescription"}, + 500: {"description": "Classification failed"}, + }, +} + +CLASSIFY_ST_DESCRIPTION_DOC = { + "tags": ["Classification"], + "parameters": [ + { + "in": "body", + "name": "body", + "required": True, + "schema": { + "type": "object", + "required": ["projectDescription"], + "properties": { + "projectName": {"type": "string", "example": "My Project"}, + "projectUrl": { + "type": "string", + "example": "https://github.com/org/repo", + }, + "projectDescription": { + "type": "string", + "example": "Open source project for digital education.", + }, + }, + }, + } + ], + "responses": { + 200: {"description": "SDG predictions"}, + 400: {"description": "Missing projectDescription"}, + 500: {"description": "Classification failed"}, + }, +} + +CLASSIFY_ST_URL_DOC = { + "tags": ["Classification"], + "parameters": [ + { + "in": "body", + "name": "body", + "required": True, + "schema": { + "type": "object", + "required": ["projectDescription", "projectUrl"], + "properties": { + "projectName": {"type": "string", "example": "My Project"}, + "projectUrl": { + "type": "string", + "example": "https://github.com/org/repo", + }, + "projectDescription": { + "type": "string", + "example": "Required by current route validation.", + }, + }, + }, + } + ], + "responses": { + 200: {"description": "SDG predictions"}, + 400: {"description": "Invalid request or repository URL"}, + 500: {"description": "Classification failed"}, + }, +} + +OSDG_API_DOC = { + "tags": ["External"], + "parameters": [ + { + "in": "body", + "name": "body", + "required": True, + "schema": { + "type": "object", + "required": ["projectDescription"], + "properties": { + "projectName": {"type": "string", "example": "My Project"}, + "projectUrl": { + "type": "string", + "example": "https://github.com/org/repo", + }, + "projectDescription": { + "type": "string", + "example": "Project summary text.", + }, + }, + }, + } + ], + "responses": { + 200: {"description": "External API predictions"}, + 400: {"description": "Missing projectDescription"}, + 500: {"description": "External API request failed"}, + }, +}