Repository navigation
Description
Use case
Our API runs behind a Lambda Function URL and its handlers read app.current_event.request_context.http.source_ip and .user_agent. Since 3.39 the same HttpResolverLocal app works both in Lambda and under uvicorn, which lets us drop a separate local Lambda emulator.
Under ASGI, though, HttpProxyEvent.from_asgi only copies the method, path, headers, body and query string:
powertools-lambda-python/aws_lambda_powertools/event_handler/http_resolver.py
Lines 108 to 141 in 67b73a5
| def from_asgi(cls, scope: Mapping[str, Any], body: bytes | None = None) -> HttpProxyEvent: | |
| """ | |
| Create an HttpProxyEvent from an ASGI scope dict. | |
| Parameters | |
| ---------- | |
| scope : dict | |
| ASGI scope dictionary | |
| body : bytes, optional | |
| Request body | |
| Returns | |
| ------- | |
| HttpProxyEvent | |
| Event object compatible with Powertools resolvers | |
| """ | |
| # Extract headers from ASGI format [(b"key", b"value"), ...] | |
| headers: dict[str, str] = {} | |
| for key, value in scope.get("headers", []): | |
| header_name = key.decode("utf-8").lower() | |
| header_value = value.decode("utf-8") | |
| # Handle duplicate headers by joining with comma | |
| if header_name in headers: | |
| headers[header_name] = f"{headers[header_name]}, {header_value}" | |
| else: | |
| headers[header_name] = header_value | |
| return cls( | |
| method=scope["method"], | |
| path=scope["path"], | |
| headers=headers, | |
| body=body, | |
| query_string=scope.get("query_string", b"").decode("utf-8"), | |
| ) |
The raw request context falls back to a stub with only stage, requestId and http.method/path:
powertools-lambda-python/aws_lambda_powertools/event_handler/http_resolver.py
Lines 90 to 95 in 67b73a5
| "requestContext": request_context | |
| or { | |
| "stage": "local", | |
| "requestId": "local-request-id", | |
| "http": {"method": method.upper(), "path": path}, | |
| }, |
HttpProxyEvent also has no request_context property, so code that reads the caller's address or user agent from the request context raises AttributeError locally, even though the ASGI scope has client and the headers have user-agent.
Solution/User Experience
Fill the request context from the ASGI scope in from_asgi: the source IP from scope["client"] and the user agent from the user-agent header, and expose it on the local event, which today has no request_context property.
It would also help to let an app choose the local event shape, so an app written for HTTP API or Function URL events reads request_context.http locally the same way it does in Lambda.
Alternative solutions
We subclass `HttpResolverLocal`: `asgi_handler` keeps the client address in a ContextVar, and `_to_proxy_event` rebuilds the local event as a version 2.0 event with `requestContext.http` (method, path, sourceIp, userAgent, stage). It works, but it relies on the private `_to_proxy_event` and on `_state` for a typed `current_event`.How we checked it, on 3.39.0: under uvicorn, current_event is an HttpProxyEvent with no request_context property, and its raw request context has only stage, requestId and http.method/path. With the subclass, the same app records the client address and user agent, and our existing tests still resolve version 2.0 Function URL events through it (realistic events in tests, not a deployed function).
This issue was drafted with an AI assistant.
Acknowledgment
- This feature request meets Powertools for AWS Lambda (Python) Tenets
- Should this be considered in other Powertools for AWS Lambda languages? i.e. Java, TypeScript, and .NET
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTriage
Activity
boring-cyborg commentedon Nov 13, 2026
Thanks for opening your first issue here! We'll come back to you as soon as we can.
In the meantime, check out the #python channel on our Powertools for AWS Lambda Discord: Invite link
powertools-for-aws-oss-automation commentedon Nov 13, 2026
Thanks for opening your first issue here! We'll come back to you as soon as we can.
In the meantime, check out our GitHub Discussions: Join the conversation
leandrodamascena commentedon Nov 15, 2026
I like this.
HttpResolverLocalunder uvicorn should give handlers the samerequest_contextfields they read in Lambda, at leasthttp.source_ip,http.user_agent,http.method,http.pathand the headers, filled from the ASGI scope. Anything Lambda-specific stays as it is today. Accepting for 3.42.0. Do you want to send the PR? You clearly know the code path.