Coverage for src/app/api/bp_api.py: 85%

33 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-03-26 21:48 -0400

1"""Flask Blueprint for the Web API that runs the CueCode runtime algorithm""" 

2 

3from functools import wraps 

4 

5from flask import Blueprint, current_app, jsonify, request 

6 

7from common.models.cuecode_config import CuecodeConfig 

8from runtime.generate_api_payloads import simple_endpoint_search 

9 

10API_KEY = "TEST_API_KEY" 

11 

12 

13def authenticate(f): 

14 """Decorator to enforce API key authentication""" 

15 

16 @wraps(f) 

17 def decorated_function(*args, **kwargs): 

18 api_key = request.headers.get("Authorization") 

19 if api_key != API_KEY: 

20 return jsonify({"error": "Unauthorized"}), 401 

21 return f(*args, **kwargs) 

22 

23 return decorated_function 

24 

25 

26def create_blueprint(): 

27 """Flask Blueprint for the Web API that runs the CueCode runtime algorithm""" 

28 

29 api_bp = Blueprint("api/v0", __name__) 

30 

31 @api_bp.errorhandler(404) 

32 def not_found(): 

33 return jsonify({"error": "Not Found"}), 404 

34 

35 @api_bp.route("/") 

36 @authenticate 

37 def index(): 

38 # pylint: disable-next=fixme 

39 # TODO: decorator for API key session handling. 

40 return jsonify({"example": "JSON"}) 

41 

42 @api_bp.route( 

43 "/openapi/<cuecode_config_id>/show-endpoint-selections-for-input/", 

44 methods=["POST"], 

45 ) 

46 @authenticate 

47 def show_endpoint_selections_for_input(cuecode_config_id): 

48 """Get the endpoints that the runtime algorithm selects 

49 for a given natural language text. Results are nondeterministic.""" 

50 data = request.get_json() 

51 endpoints = simple_endpoint_search(cuecode_config_id, data["text"]) 

52 result = {"endpoints": endpoints} 

53 return jsonify(result) 

54 

55 # Recommended Blueprint 404 handling from Flask Docs 

56 # (https://flask.palletsprojects.com/en/stable/blueprints/#blueprint-error-handlers) 

57 # does not work, so we add a catch-all handler. 

58 # The answer at https://stackoverflow.com/a/39770599 

59 # confirms this approach. 

60 @api_bp.route("/<path:path>") 

61 def endpoint_not_round(path): # pylint: disable=unused-argument 

62 return jsonify({"error": "Endpoint not found."}) 

63 

64 return api_bp