bref
bref copied to clipboard
Support for custom HTTP invocations
Bref web functions expect to be invoked by either an API Gateway or ALB. It would be nice if Bref was able to handle HTTP events from different types of sources. However, there are many other invocation methods, including direct invocation using the AWS CLI, but invoking the lambda function without an API Gateway or ALB event type results in the following error (which is currently the expected behavior):
{
"errorType": "Bref\\Event\\InvalidLambdaEvent",
"errorMessage": "This handler expected to be invoked with a API Gateway or ALB event. Instead, the handler was invoked with invalid event data: null",
"stackTrace": [
"#0 \/var\/task\/vendor\/bref\/bref\/src\/Event\/Http\/HttpHandler.php(23): Bref\\Event\\Http\\HttpRequestEvent->__construct()",
"#1 \/var\/task\/vendor\/bref\/bref\/src\/Runtime\/Invoker.php(29): Bref\\Event\\Http\\HttpHandler->handle()",
"#2 \/var\/task\/vendor\/bref\/bref\/src\/Runtime\/LambdaRuntime.php(91): Bref\\Runtime\\Invoker->invoke()",
"#3 \/var\/runtime\/bootstrap(43): Bref\\Runtime\\LambdaRuntime->processNextEvent()",
"#4 {main}"
]
}
One tool that has Lambda integration is Envoy Proxy which requires the Lambda to return an API Gateway V2 type response but the incoming request/event looks like this:
{
"rawPath": "/path/to/resource",
"method": "GET|POST|HEAD|...",
"headers": {"header-key": "header-value", ... },
"queryStringParameters": {"key": "value", ...},
"body": "...",
"isBase64Encoded": true|false
}
I think there are some things to consider if this was to be implemented.
Accepting the event type We could update the HttpHandler to also accept the payload above, but then the response (as the code is right now) is looking for a version 2 in the payload to return the API Gateway V2 response.
Force returning V2 response
That could be resolved by setting some kind of variable BREF_RESPONSE_V2
(naming leaves a lot for desire) and when that is set the response will always be return as V2 compatible.
Wanted to start the discussion before making a PR to add this feature.
Example with Envoy
If you wanted to try this with Envoy, you can use this Envoy configuration file (change ACCOUNT
, FUNCTION
, and REGION
to the correct values) and running envoy -c envoy.yaml
.
Note: hitting port 10000 in a browser will return an auth error, you must use something like Insomnia and send a
Host
header to make it work.
static_resources:
listeners:
- name: ingress
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: http_ingress
http_filters:
- name: envoy.filters.http.aws_lambda
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.aws_lambda.v3.Config
arn: arn:aws:lambda:REGION:ACCOUNT:function:FUNCTION
payload_passthrough: false
- name: envoy.filters.http.router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: lambda_egress_gateway
clusters:
- name: lambda_egress_gateway
connect_timeout: 10s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
metadata:
filter_metadata:
com.amazonaws.lambda:
egress_gateway: true
load_assignment:
cluster_name: lambda_egress_gateway
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: lambda.REGION.amazonaws.com
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: "*.amazonaws.com"
Just to clarify, the Envoy proxy payload is not following the API Gateway v2 payload?
Something that will be on the new runtime i BREF-specific input that can be understood as an HTTP request, such as BREF_METHOD
and BREF_BODY
@mnapoli you can define payload_passthrough
as false and Envoy will transform the HTTP request into the following JSON payload:
{
"rawPath": "/path/to/resource",
"method": "GET|POST|HEAD|...",
"headers": {"header-key": "header-value", ... },
"queryStringParameters": {"key": "value", ...},
"body": "...",
"isBase64Encoded": true|false
}
@deleugpn would that mean we could set configure the handler to check for BREF_RESPONSE_V2
to force it to return API Gateway Version 2 responses?
@jasonmccallister ok so what is not working? Can you clarify what the problem is here?
and Envoy will transform the HTTP request into the following JSON payload:
Is that compatible with API Gateway payload v2?
@mnapoli there are two issues.
-
The Envoy request payload is not v2 compatible and is throwing an exception here.
-
The Envoy response is v2 compatible and only V2 compatible. However, Bref checks if the event is for format v2 and there is no way to override the response.
As far as #1, we could add another if statement that checks for $event['method']
that is sent by Envoy, but that won't resolve #2 where it has to return a v2 response.
We could resolve #2 by updating the code here to something like this:
public function isFormatV2(): bool
{
return $this->payloadVersion === 2.0 || array_key_exists('method', $this->event);
}
Diving through the existing code and talking it out here, it seems like it might not be a large lift to add support for this type of payload. Want me to make a PR with those proposed changes? I'm sure there are some other methods that will probably need updates.