Starting an issue to work out the how the API would work. I think doing something like:
from chalice import Chalice
app = Chalice(app_name="helloworld", listener='alb')
omitting listener will default to 'apigateway'
Because things like authorizers just aren't compatible across listeners, it makes sense to make listener part of the app construction, as opposed to something that is decided at deploy time. I'm sure there is more I'm not thinking of.
Yeah that's really interesting and something I'd like to support. Presumably we would also create the ALB for you? It'd be similar to how we create the rest API in API gateway for you. If so, we'd need some way for people to configure the various parameters needed to create an ALB so I'm not sure where or how that would look like.
Or perhaps you create your ALB outside of chalice and then just tell us which ALB we should use.
The docs also show that the returned response is slightly different, or at least supports more than what API gateway supports so we'll likely need runtime support to know which JSON structure to return from the lambda function.
Because things like authorizers just aren't compatible across listeners, it makes sense to make listener part of the app construction, as opposed to something that is decided at deploy time. I'm sure there is more I'm not thinking of.
Many of the event sources of a chalice app already don't require API Gateway, such as @app.schedule and @app.on_sns_message. Seems like this is something that should be configured as a parameter to @app.route since that is what is actually being affected, or if the interfaces turn out to be too different an entirely new annotation might be warranted. Keeping it out of the app definition also allows for mixing API gateway and ALB routes in the same app if someone has that use case for some reason.
If so, we'd need some way for people to configure the various parameters needed to create an ALB so I'm not sure where or how that would look like.
Or perhaps you create your ALB outside of chalice and then just tell us which ALB we should use.
Why not both?
I'm trying to eliminated choices that can't be undone, APIs are forever. That being said, I think providing an ALB that Chalice will use seems like a reasonable choice. It's an exercise to the reader to create the LB and the Listener, and Chalice creates the TargetGroup for the Lambda and plugs it in.
Keeping it out of the app definition also allows for mixing API gateway and ALB routes in the same app if someone has that use case for some reason.
So something like
@app.alb('/', Listener='arn:...')
def func():
...
We somehow need to pass the Listener to this, and it seems verbose to pass the ARN for every function. I'm not in favor of this approach. We should either hijack the Chalice constructor to make the app an ALB, or we create a new constructor, which makes an ALB based app. I'm not familiar enough with the code base to know what would make the most sense, but from the outside, they seem similar enough that it doesn't matter which is chosen.
I'm interested in this as ALB allows one to bypass the 30s API Gateway timeout (and perhaps other types of API Gateway limitations, for example content-type negotiation issues in API Gateway).
Does anyone have clarity on what the Chalice API for this should look like?
Also very interested in this, especially with the @app.alb annotation API described by @karlw00t.
Our biggest feature gain from this would be to have internal-only services inside our VPC provided by chalice Lambdas.
I had to dismantle an app I'd built on Chalice, and port it to normal Lambda, because of this missing feature.
FYI, I have added ALB-Lambda integration support to Domovoi (https://github.com/kislyuk/domovoi). In Domovoi, the handler looks like this:
@app.alb_target()
def serve(event, context):
return dict(statusCode=200,
statusDescription="200 OK",
isBase64Encoded=False,
headers={"Content-Type": "application/json"},
body=json.dumps({"hello": "world"}))
It successfully bypasses the 30s timeout and content-type negotiation limits of API Gateway, however, ALB has its own limitations: when calling Lambdas, it has a 1MB request and response size limit (https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html).
I had to dismantle an app I'd built on Chalice, and port it to normal Lambda, because of this missing feature.
I had this issue as well.
We're planning on using the lambdas as part of a broader application, and we would like to reuse our existing ALBs for this so we can leverage other pieces of what we've already built.
So +1 for this.
@kislyuk unfortunately your solution won't work either; we want to be able to re-use our existing ALB(s)
I have a use case where I can not use Amazon API Gateway. This'd be a perfect solution if chalice could serve the ALB requests. Thanks @kislyuk for your solution, it woks for me! However, I wish to see chalice supports this feature soon.
https://github.com/trustpilot/python-lambdarest seems like a good alternative for simple routing while this feature is not available.
Another use case is the deployment of Chalice apps to a VPC. API Gateway does not work seamlessly in VPCs: specifically it doesn't recognize the hostname from a VPC Endpoint as a valid Host header for the API, and the native DNS name doesn't resolve outside the VPC (so it fails in Direct Connect, site-to-site VPN, and some Transit Gateway based environments). Having Chalice manage the ALB would be nice in this scenario, where I have an app that already works in API Gateway and I just want to deploy it in a VPC.
Any update for this ?
Most helpful comment
Another use case is the deployment of Chalice apps to a VPC. API Gateway does not work seamlessly in VPCs: specifically it doesn't recognize the hostname from a VPC Endpoint as a valid Host header for the API, and the native DNS name doesn't resolve outside the VPC (so it fails in Direct Connect, site-to-site VPN, and some Transit Gateway based environments). Having Chalice manage the ALB would be nice in this scenario, where I have an app that already works in API Gateway and I just want to deploy it in a VPC.