Expected Behaviour
When cors=CORSConfig(...) is passed to HttpResolverLocal, browser preflight (OPTIONS) requests should return 204 with the appropriate Access-Control-* headers, just like APIGatewayRestResolver does.
Current Behaviour
OPTIONS requests fall through to _handle_not_found_async, which has no CORS preflight branch. They get treated as 404s, and because the not-found path uses lookup_exception_handler(NotFoundError) which walks the MRO, any generic @app.exception_handler(Exception) handler picks them up and returns 500 with no CORS headers. The browser then blocks the actual request.
Code snippet
import json
from aws_lambda_powertools.event_handler import HttpResolverLocal, Response
from aws_lambda_powertools.event_handler.api_gateway import CORSConfig
app = HttpResolverLocal(cors=CORSConfig(allow_origin="*"))
@app.post("/items")
def create_item():
return {"ok": True}
@app.exception_handler(Exception)
def handle_server_error(ex: Exception):
return Response(
status_code=500,
content_type="application/json",
body=json.dumps({"error": "internal"}),
)
Possible Solution
Mirror the CORS preflight branch from ApiGatewayResolver._handle_not_found into _handle_not_found_async:
if self._cors and self.current_event.http_method.upper() == "OPTIONS":
headers = {
"Access-Control-Allow-Methods": CORSConfig.build_allow_methods(self._cors_methods),
}
response = Response(status_code=204, content_type=None, headers=headers, body="")
else:
# existing not-found logic
Steps to Reproduce
uvicorn app:app --port 3001
curl -i -X OPTIONS http://127.0.0.1:3001/items \
-H 'Origin: http://localhost:3000' \
-H 'Access-Control-Request-Method: POST'
# → 500, no Access-Control-* headers
Powertools for AWS Lambda (Python) version
latest
AWS Lambda function runtime
3.10
Packaging format used
PyPi
Debugging logs
Expected Behaviour
When cors=CORSConfig(...) is passed to HttpResolverLocal, browser preflight (OPTIONS) requests should return 204 with the appropriate Access-Control-* headers, just like APIGatewayRestResolver does.
Current Behaviour
OPTIONS requests fall through to _handle_not_found_async, which has no CORS preflight branch. They get treated as 404s, and because the not-found path uses lookup_exception_handler(NotFoundError) which walks the MRO, any generic @app.exception_handler(Exception) handler picks them up and returns 500 with no CORS headers. The browser then blocks the actual request.
Code snippet
Possible Solution
Mirror the CORS preflight branch from ApiGatewayResolver._handle_not_found into _handle_not_found_async:
Steps to Reproduce
Powertools for AWS Lambda (Python) version
latest
AWS Lambda function runtime
3.10
Packaging format used
PyPi
Debugging logs