Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(apigateway): define function to handle not found requests #65

Closed
rtcnerd opened this issue Dec 10, 2021 · 13 comments
Closed

feature(apigateway): define function to handle not found requests #65

rtcnerd opened this issue Dec 10, 2021 · 13 comments
Labels

Comments

@rtcnerd
Copy link

rtcnerd commented Dec 10, 2021

Executing the following code does not trigger the rules. Ideally I would expect the rule="/not-found-error" to be triggered when an incorrect path is sent. The print statement is never printed. I get the default value. Am I missing something?

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver
from aws_lambda_powertools.event_handler.exceptions import (
BadRequestError,
InternalServerError,
NotFoundError,
ServiceError,
UnauthorizedError,
)

tracer = Tracer()
logger = Logger()

app = ApiGatewayResolver()

@app.get(rule="/bad-request-error")
def bad_request_error():
# HTTP 400
raise BadRequestError("Missing required parameter")

@app.get(rule="/unauthorized-error")
def unauthorized_error():
# HTTP 401
raise UnauthorizedError("Unauthorized")

@app.get(rule="/not-found-error")
def not_found_error():
# HTTP 404
print("Not found")
raise NotFoundError

@app.get(rule="/internal-server-error")
def internal_server_error():
# HTTP 500
raise InternalServerError("Internal server error")

@app.get(rule="/service-error", cors=True)
def service_error():
raise ServiceError(502, "Something went wrong!")
# alternatively
# from http import HTTPStatus
# raise ServiceError(HTTPStatus.BAD_GATEWAY.value, "Something went wrong)

def handler(event, context):
return app.resolve(event, context)

@boring-cyborg
Copy link

boring-cyborg bot commented Dec 10, 2021

Thanks for opening your first issue here! We'll come back to you as soon as we can.

@heitorlessa
Copy link
Contributor

Hey @rtcnerd, thanks for raising this with us.

Routes are exact matches or regex patterns. This means, that print statement will only execute if an incoming request matches that route "/not-found-error".

There is an issue/PR to add support for handling 404s and the likes.

If there's a particular UX you'd like us to provide please do let us know!

@rtcnerd
Copy link
Author

rtcnerd commented Dec 11, 2021

@heitorlessa what is the best way to handle 404 event and send back a custom message?

@heitorlessa
Copy link
Contributor

@heitorlessa what is the best way to handle 404 event and send back a custom message?

Within your Lambda Handler, inspect the response from "app.resolve(event, context)" and see if "statusCode" is 404.

By default, docs suggest to simply "return app.resolve(event, context)".

At least until we provide a more streamlined way like "@app.not_found" and "@app.exception_handler()"

@jakebrinkmann
Copy link

🤔 hmmm, too bad there isn't a way to override the serializer in ApiGatewayResolver for errors

https://github.com/awslabs/aws-lambda-powertools-python/blob/be6e722e3d552c56ef916c87dffeb40e394fe499/aws_lambda_powertools/event_handler/api_gateway.py#L612-L617

edit: this is what I will do for now:

    try:
        response = app.resolve(event, context)

    except Exception:
        response = {
            "statusCode": 500,
            "message": {
                "type": "https://datatracker.ietf.org/doc/html/rfc7807",
                "title": "Internal Server Error",
                "detail": "An unexpected error has occurred",
                "status": 500,
            },
        }

    if response["statusCode"] >= 400:
        return Response(
            status_code=response["statusCode"],
            content_type="application/problem+json",
            body=response["message"],
        )

@heitorlessa
Copy link
Contributor

heitorlessa commented Dec 16, 2021 via email

@heitorlessa heitorlessa changed the title Dec 17, 2021
@heitorlessa
Copy link
Contributor

heitorlessa commented Dec 20, 2021

EDIT: Correct syntax error on @app.not_found

Done - it'll be available as part of today's release. Both not found and any exception you want to handle

app = ApiGatewayResolver()
logger = Logger()


@app.exception_handler(SomeKindOfError)
def handle_error(ex: SomeKindOfError):
   print(f"request path is '{app.current_event.path}'")
   return Response(status_code=418, content_type=content_types.TEXT_HTML, body=str(ex))


@app.not_found
def handle_not_found(exc: NotFoundError):
    return Response(status_code=404, content_type=content_types.TEXT_PLAIN, body="I am a teapot!")


@app.exception_handler(ServiceError)
def service_error(ex: ServiceError):
    logger.debug(f"Log out sensitive stuff: {ex.msg}")
    return Response(
        status_code=ex.status_code,
        content_type=content_types.APPLICATION_JSON,
        body="CUSTOM ERROR FORMAT",
    )


@app.get("/my/path")
def call_with_error() -> Response:
   raise SomeKindOfError("Foo!")


@app.get("/my/path2")
def call_with_error_sensitive() -> Response:
   raise InternalServiceError("Foo!")


def lambda_handler(event, context):
   return app(event, context)

@heitorlessa heitorlessa transferred this issue from aws-powertools/powertools-lambda-python Dec 20, 2021
@heitorlessa heitorlessa changed the title feature: define function to handle not found requests in Api Gateway feature(apigateway): define function to handle not found requests Dec 20, 2021
@heitorlessa
Copy link
Contributor

hey @rtcnerd this is now available as part of today's 1.23.0 release :) Thank you again for this feature request!

@rtcnerd
Copy link
Author

rtcnerd commented Dec 21, 2021

@heitorlessa many thanks for introducing the new feature. However when I try executing your sample code on aws, i get the following error for not found:
[ERROR] TypeError: not_found() missing 1 required positional argument: 'func'
Traceback (most recent call last):
File "/var/lang/lib/python3.9/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1030, in _gcd_import
File "", line 1007, in _find_and_load
File "", line 986, in _find_and_load_unlocked
File "", line 680, in _load_unlocked
File "", line 850, in exec_module
File "", line 228, in _call_with_frames_removed
File "/var/task/lambda_function.py", line 19, in
@app.not_found()

@heitorlessa
Copy link
Contributor

@heitorlessa many thanks for introducing the new feature. However when I try executing your sample code on aws, i get the following error for not found:

[ERROR] TypeError: not_found() missing 1 required positional argument: 'func'

Traceback (most recent call last):

File "/var/lang/lib/python3.9/importlib/init.py", line 127, in import_module

return _bootstrap._gcd_import(name[level:], package, level)

File "", line 1030, in _gcd_import

File "", line 1007, in _find_and_load

File "", line 986, in _find_and_load_unlocked

File "", line 680, in _load_unlocked

File "", line 850, in exec_module

File "", line 228, in _call_with_frames_removed

File "/var/task/lambda_function.py", line 19, in

@app.not_found()

🤦‍♂️ there's a syntax error in my comment up there - () - decorator should be @app.not_found not @app.not_found() or else you'll get the error you've got, my apologies.

The official docs are correct

https://awslabs.github.io/aws-lambda-powertools-python/latest/core/event_handler/api_gateway/#handling-not-found-routes

Let me know if you're still experiencing the same issue with the correct sample

@heitorlessa heitorlessa reopened this Dec 21, 2021
@heitorlessa heitorlessa added the Proposed Community submited label Dec 22, 2021
@michaelbrewer
Copy link
Contributor

@heitorlessa - should i accept @app.not_found() has well? just to safe?

@michaelbrewer
Copy link
Contributor

@heitorlessa @rtcnerd - sorry about the errors with () I have added support for that too:

@michaelbrewer
Copy link
Contributor

@rtcnerd - anything else missing from this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants