• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

digiteinfotech / kairon / 21936128812

12 Feb 2026 06:30AM UTC coverage: 91.139% (+0.001%) from 91.138%
21936128812

Pull #2338

github

web-flow
Merge a76836439 into 2946d3506
Pull Request #2338: Static callback fix 2

6 of 6 new or added lines in 3 files covered. (100.0%)

22 existing lines in 3 files now uncovered.

30208 of 33145 relevant lines covered (91.14%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.22
/kairon/async_callback/router/pyscript_callback.py
1
from typing import Optional
1✔
2
from blacksheep import Router, Request, Response as BSResponse, json
1✔
3
from blacksheep.contents import JSONContent
1✔
4

5
from loguru import logger
1✔
6

7
from kairon.async_callback.auth import CallbackAuthenticator
1✔
8
from kairon.async_callback.processor import CallbackProcessor
1✔
9
from kairon.async_callback.utils import CallbackUtility
1✔
10
from kairon.exceptions import AppException
1✔
11
from kairon.shared.callback.data_objects import PyscriptPayload
1✔
12
from kairon.shared.callback.data_objects import CallbackRequest
1✔
13

14

15
router = Router()
1✔
16

17

18
async def process_router_message(token: str, identifier: Optional[str] = None, req_type: str = 'GET', request: Request = None) -> BSResponse:
1✔
19
    """Process the incoming request for the callback."""
20
    if not request:
1✔
21
        raise AppException("Request is not valid!")
1✔
22

23
    data = {
1✔
24
        'type': req_type,
25
        'body': None,
26
        'params': {},
27
        'headers': {}
28
    }
29

30
    if request.query:
1✔
UNCOV
31
        data['params'].update({key: request.query.get(key) for key in request.query.keys()})
×
32

33
    try:
1✔
34
        data['headers'] = {key.decode(): value.decode() for key, value in request.headers.items()}
1✔
35
    except Exception as e:
1✔
36
        logger.exception('could not parse headers')
1✔
37

38
    try:
1✔
39
        req_data = None
1✔
40

41
        try:
1✔
42
            req_data = await request.json()
1✔
43
            logger.info('Request Body type: json')
1✔
44
        except Exception as e:
1✔
45
            logger.info('Request Body type: text')
1✔
46
            req_data = await request.read()
1✔
47
            if req_data and len(req_data) > 0:
1✔
48
                req_data = req_data.decode('utf-8')
1✔
49
            else:
UNCOV
50
                req_data = None
×
51

52
        if req_data:
1✔
53
            data.update({"body": req_data})
1✔
54

55
        request_source = request.scope.get("client", ["unknown"])[0]
1✔
56
        logger.info(f"Request source IP: {request_source}")
1✔
57
        logger.info(f"Data from request: {data}")
1✔
58
        print(request_source)
1✔
59

60
        data, message, error_code, response_type = await CallbackProcessor.process_async_callback_request(
1✔
61
            token, identifier, data, request_source
62
        )
63

64
        return CallbackUtility.return_response(data, message, error_code, response_type)
1✔
65
    except AppException as ae:
1✔
66
        logger.error(f"AppException: {ae}")
1✔
67
        if len(ae.args) >= 2:
1✔
68
            mssg = ae.args[0]
1✔
69
            error_code = ae.args[1]
1✔
70
            return BSResponse(
1✔
71
                status=200,
72
                content=JSONContent({
73
                    "message": mssg,
74
                    "data": None,
75
                    "error_code": error_code,
76
                    "success": False,
77
                })
78
            )
79
        else:
80
            return BSResponse(
1✔
81
                status=400,
82
                content=JSONContent({
83
                    "message": str(ae),
84
                    "error_code": 400,
85
                    "data": None,
86
                    "success": False,
87
                })
88
            )
89
    except Exception as e:
1✔
90
        logger.exception(e)
1✔
91
        return BSResponse(
1✔
92
            status=500,
93
            content=JSONContent({
94
                "message": str(e),
95
                "error_code": 400,
96
                "data": None,
97
                "success": False
98
            })
99
        )
100

101

102
@router.route("/callback/d/{identifier}/{token}", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
1✔
103
async def execute_async_action(request: Request, identifier: str, token: str) -> BSResponse:
1✔
104
    return await process_router_message(token, identifier, request.method, request)
1✔
105

106

107
@router.route("/callback/s/{token}", methods=["POST", "PUT", "PATCH"])
1✔
108
async def execute_async_action_standalone(request: Request, token: str) -> BSResponse:
1✔
109
    return await process_router_message(token, None, request.method, request)
1✔
110

111
@router.post("/main_pyscript/execute-python")
1✔
112
async def trigger_restricted_python(payload: PyscriptPayload):
1✔
113
    try:
1✔
114
        result = CallbackUtility.main_pyscript_handler({
1✔
115
            "source_code": payload.source_code,
116
            "predefined_objects": payload.predefined_objects or {}
117
        }, None)
118
        return {"success": True, **result}
1✔
119
    except Exception as e:
1✔
120
        return json({"success": False, "error": str(e)}, status=422)
1✔
121

122
@router.post("/callback/handle_event")
1✔
123
async def handle_callback(
1✔
124
    request: Request,
125
    body: CallbackRequest
126
):
127
    await CallbackAuthenticator.verify(request)
1✔
128
    payload = body.data
1✔
129
    try:
1✔
130
        result = CallbackUtility.execute_script(
1✔
131
            payload.get("source_code"),
132
            payload.get("predefined_objects", {})
133
        )
134
        return {"statusCode": 200, "body": result}
1✔
135
    except Exception as e:
1✔
136
        return {"statusCode": 422, "body": str(e)}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc