Skip to content

Bug: APIGatewayRestResolver does not capture path segment with + sign #3006

Closed
@nejcskofic

Description

@nejcskofic

Expected Behaviour

If handler is registered for dynamic path, I would expect that segment containing plus sign is captured.

Example:

@app.get("/dummy/<value>")
def handler(value: str): ...

Resolver is invoked with: GET /dummy/a+b

Current Behaviour

Resolver returns 404 error.

Code snippet

from dataclasses import dataclass

import pytest
from aws_lambda_powertools.event_handler import APIGatewayRestResolver


@pytest.fixture
def lambda_context():
    @dataclass
    class LambdaContext:
        function_name: str = "test"
        memory_limit_in_mb: int = 128
        invoked_function_arn: str = "arn:aws:lambda:eu-west-1:123456789012:function:test"
        aws_request_id: str = "da658bd3-2d6f-4e7b-8ec2-937234644fdc"

    return LambdaContext()


def test_api_gateway_plus_path_capturing(lambda_context):
    app = APIGatewayRestResolver()

    @app.get("/dummy/<value>")
    def handler(value: str):
        assert value == "a+b"
        return {}

    response = app.resolve(
        {
            "path": "/dummy/a+b",
            "httpMethod": "GET",
            "requestContext": {"requestId": "227b78aa-779d-47d4-a48e-ce62120393b8"}
        },
        lambda_context
    )

    assert response["statusCode"] == 200

Possible Solution

api_gateway.pyL44 contains definition of safe characters. This list is incomplete. By rfc3986 Section 3.3 path is built from segments where segments can contain sub-delims which are defined as:

sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
                  / "*" / "+" / "," / ";" / "="

API Gateway resolver is using this list of characters when building route regex:

_SAFE_URI = "-._~()'!*:@,;="

Plus sign (+), dollar sign ($) and ampersand sign (&) are missing from that list. Adding them would resolve this issue.

Steps to Reproduce

Run above code snippet as pytest test.

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.10

Packaging format used

PyPi

Debugging logs

No response

Metadata

Metadata

Labels

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions