bedrock.endpoints.response

 1import json  # pragma: unit
 2import traceback  # pragma: unit
 3from bedrock.config import get_config_params  # pragma: unit
 4from bedrock.exceptions.bedrock_exception import BedrockException  # pragma: unit
 5from bedrock.log import log_config  # pragma: unit
 6from bedrock.endpoints.dto.bedrock_response import BedrockResponse, resolve_response, \
 7    has_envelope_header, BedrockErrorResponse  # pragma: unit
 8
 9log = log_config("response_helper")  # pragma: unit
10
11
12def respond(http_code: int, body: BedrockResponse | dict | list, event: dict | None = None):  # pragma: unit
13    """
14    Format a response to be returned via API Gateway with the given HTTP code and body.
15    You're unlikely to need to use this unless implementing your own handler.
16
17    This method expects a BedrockResponse, but it will try to convert a dict or list to a BedrockResponse.
18    The conversion isn't perfect since this method may not have enough information.
19
20    :param http_code: The http code to return
21    :param body: A BedrockResponse object (or something to be converted into one) to return as json
22    :param event: The event that triggered this response
23    """
24    _event = event if event else body.event if isinstance(body, BedrockResponse) else {}
25    try:
26        resolved_body = resolve_response(body, _event, {}, {})
27        if has_envelope_header(resolved_body.event):
28            body_string = json.dumps(resolved_body.as_json())
29        else:
30            body_string = json.dumps(resolved_body.as_unenveloped_json())
31    except Exception as e:
32        log.error(f"Could not convert body to json: {str(e)}\nEvent: {str(_event)}")
33        log.error(traceback.format_exc())
34        body_string = json.dumps({
35            "error": "Oops",
36            "originalException": f"{traceback.format_exc()}"
37        })
38    return {
39        'statusCode': http_code,
40        'body': body_string,
41        'headers': {
42            "Access-Control-Allow-Origin": "*",
43            "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
44            "Access-Control-Allow-Headers": "*"
45        },
46        "isBase64Encoded": False
47    }
48
49
50def err(error: str | BedrockException,
51        exception: str | Exception = None,
52        forced_http_code: int = None,
53        event: dict | None = None,
54        error_code: str = "-1"):  # pragma: unit
55    """
56    Format an error response to be returned via API Gateway. By default, it takes the error code from the exception,
57    but you can override it with `forced_http_code`.
58    :param error: A user-friendly error.
59    :param error_code: A machine-friendly error code.
60    :param exception: The original exception that caused the error. This is only used in non-production environments.
61    :param forced_http_code: Override the exception's http code with this one.
62    :param event: The request event.
63    """
64    config = get_config_params()
65    is_prod = config["environment"] == "production"
66    _event = event if event else {}
67    try:
68        try:
69            message = error.message
70        except:
71            message = str(error)
72        try:
73            original_exception = error.original_exception if exception is None else exception
74        except:
75            original_exception = None
76        try:
77            http_code = error.error_code if forced_http_code is None else forced_http_code
78        except:
79            http_code = 500 if forced_http_code is None else forced_http_code
80
81        error_response = BedrockErrorResponse({
82            "code": error_code,
83            "message": message,
84            "exception": str(original_exception) if original_exception and not is_prod else None
85        }, _event)
86    except Exception as e:  # pragma: no cover
87        log.exception(e)
88        http_code = 500
89        error_response = BedrockErrorResponse({
90            "code": "-2",
91            "message": "This error was so bad, I couldn't even generate an error for it.",
92            "exception": str(e) if not is_prod else None
93        }, _event)
94    return respond(http_code, error_response)
log = <MyLogger BEDROCK-response_helper (INFO)>
def respond( http_code: int, body: bedrock.endpoints.dto.bedrock_response.BedrockResponse | dict | list, event: dict | None = None):
13def respond(http_code: int, body: BedrockResponse | dict | list, event: dict | None = None):  # pragma: unit
14    """
15    Format a response to be returned via API Gateway with the given HTTP code and body.
16    You're unlikely to need to use this unless implementing your own handler.
17
18    This method expects a BedrockResponse, but it will try to convert a dict or list to a BedrockResponse.
19    The conversion isn't perfect since this method may not have enough information.
20
21    :param http_code: The http code to return
22    :param body: A BedrockResponse object (or something to be converted into one) to return as json
23    :param event: The event that triggered this response
24    """
25    _event = event if event else body.event if isinstance(body, BedrockResponse) else {}
26    try:
27        resolved_body = resolve_response(body, _event, {}, {})
28        if has_envelope_header(resolved_body.event):
29            body_string = json.dumps(resolved_body.as_json())
30        else:
31            body_string = json.dumps(resolved_body.as_unenveloped_json())
32    except Exception as e:
33        log.error(f"Could not convert body to json: {str(e)}\nEvent: {str(_event)}")
34        log.error(traceback.format_exc())
35        body_string = json.dumps({
36            "error": "Oops",
37            "originalException": f"{traceback.format_exc()}"
38        })
39    return {
40        'statusCode': http_code,
41        'body': body_string,
42        'headers': {
43            "Access-Control-Allow-Origin": "*",
44            "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
45            "Access-Control-Allow-Headers": "*"
46        },
47        "isBase64Encoded": False
48    }

Format a response to be returned via API Gateway with the given HTTP code and body. You're unlikely to need to use this unless implementing your own handler.

This method expects a BedrockResponse, but it will try to convert a dict or list to a BedrockResponse. The conversion isn't perfect since this method may not have enough information.

Parameters
  • http_code: The http code to return
  • body: A BedrockResponse object (or something to be converted into one) to return as json
  • event: The event that triggered this response
def err( error: str | bedrock.exceptions.BedrockException, exception: str | Exception = None, forced_http_code: int = None, event: dict | None = None, error_code: str = '-1'):
51def err(error: str | BedrockException,
52        exception: str | Exception = None,
53        forced_http_code: int = None,
54        event: dict | None = None,
55        error_code: str = "-1"):  # pragma: unit
56    """
57    Format an error response to be returned via API Gateway. By default, it takes the error code from the exception,
58    but you can override it with `forced_http_code`.
59    :param error: A user-friendly error.
60    :param error_code: A machine-friendly error code.
61    :param exception: The original exception that caused the error. This is only used in non-production environments.
62    :param forced_http_code: Override the exception's http code with this one.
63    :param event: The request event.
64    """
65    config = get_config_params()
66    is_prod = config["environment"] == "production"
67    _event = event if event else {}
68    try:
69        try:
70            message = error.message
71        except:
72            message = str(error)
73        try:
74            original_exception = error.original_exception if exception is None else exception
75        except:
76            original_exception = None
77        try:
78            http_code = error.error_code if forced_http_code is None else forced_http_code
79        except:
80            http_code = 500 if forced_http_code is None else forced_http_code
81
82        error_response = BedrockErrorResponse({
83            "code": error_code,
84            "message": message,
85            "exception": str(original_exception) if original_exception and not is_prod else None
86        }, _event)
87    except Exception as e:  # pragma: no cover
88        log.exception(e)
89        http_code = 500
90        error_response = BedrockErrorResponse({
91            "code": "-2",
92            "message": "This error was so bad, I couldn't even generate an error for it.",
93            "exception": str(e) if not is_prod else None
94        }, _event)
95    return respond(http_code, error_response)

Format an error response to be returned via API Gateway. By default, it takes the error code from the exception, but you can override it with forced_http_code.

Parameters
  • error: A user-friendly error.
  • error_code: A machine-friendly error code.
  • exception: The original exception that caused the error. This is only used in non-production environments.
  • forced_http_code: Override the exception's http code with this one.
  • event: The request event.