Closed beacon-robertbreedt closed 2 years ago
So, I believe this is related to a similar issue we had with 'headers' where we had similar code to remove headers. I can't exactly recall the reason for it but you may notice there was a TODO comment to get rid of all that code in AWSUtils and delegate to Message Converter etc. . . In any event, i just pushed that change - https://github.com/spring-cloud/spring-cloud-function/commit/8bcdeb5cc2a56102dba84a3cac7df034fe8d5e59 so please try with the latest snapshot - 3.2.7-SNAPSHOT.
I'll keep it open for now
Thanks, under which repository is the snapshot available?
@beacon-robertbreedt it's here - https://repo.spring.io/snapshot
Ok, so I've done some testing and here's my results:
Function<APIGatewayV2HTTPEvent, APIGatewayV2HTTPResponse>
APIGatewayV2HTTPResponse
object with full detailsAPIGatewayV2HTTPResponse
object
Content-Type: application/json
in itContent-Type: application/octet-stream
Function<APIGatewayV2HTTPEvent, APIGatewayV2HTTPResponse>
Function<String, String>
Function<Input, Output>
Input(name=null)
) is passed to function as it does not dynamically convert to this from the APIGatewayV2HTTPEvent's body Output
classOlegz (asking on a thread that is still open),
I noticed that the AWSCompanionAutoConfiguration in not included in the spring.factories file. How is AWSTypesMessageConverter ever suppose to make its way into the path of execution?
Look at the start()
method of FunctionInvoker
ConfigurableApplicationContext context = ApplicationContextInitializer.class.isAssignableFrom(startClass)
? FunctionalSpringApplication.run(new Class[] {startClass, AWSCompanionAutoConfiguration.class}, properties)
: SpringApplication.run(new Class[] {startClass, AWSCompanionAutoConfiguration.class}, properties);
That said, i should probably rename it to just AWSCompanionConfiguration
as I can now understand your confusion.
@olegz when can we expect the next release with the fixes above?
next week or the week after
@beacon-robertbreedt while I am still looking I am also trying to figure out if you believe there is still an issue. It's a little inconclusive from your report - the first scenario where you say returns correctly as APIGatewayV2HTTPResponse object with full details
and than response body has property headers with Content-Type: application/json in it response headers has Content-Type: application/octet-stream
.
Can you please clarify?
Sure, so if the output of a function is APIGatewayV2HTTPResponse
, it seems to double wrap the response if the request is determined to be from an API gateway/LB. It's best shown with screenshots.
Request and response via LB from Postman:
Response headers: Content-Type is application/json
From AWS console, using the exact same request as above ^ retrieved from logs:
Response in AWS console:
application/json
Looks like the function's APIGatewayV2HTTPResponse is wrapped within a APIGatewayV2HTTPResponse in the console, but I'm not sure if this is an issue. If the request originates through the LB, it'll consume the first APIGatewayV2HTTPResponse as that's what it expects and forward the "body" content, which is a json encoded APIGatewayV2HTTPResponse string. This is likely where the application/octet-stream is coming from, AWS's LB itself.
I can easily work around this by specifying the output of a function to some object/class. Screenshots for that:
Postman:
response headers also show application/octet-stream
AWS Console:
application/json
So this isn't an issue with s.c.f, but found the test result interesting and worth sharing.
I am wondering on the last report for the Function<Input, Output>
test if it's possible to somehow determine/deserialise the object from the APIGatewayV2HTTPEvent body. Possibly not as it'd probably need a lot of conditional checks and added logic to determine what type it needs to deserialise into and the format of the provided data based on the Content-Type headers.
FunctionInvoker
FunctionInvoker works fine for normal java lambda functions, but what about native java lambda solutions. The FunctionInvoker is not run and instead its just CustomRuntimeInitializer > CustomRuntimeEventLoop. As you know the current solutions is doing message transformations in the AWSLambdaUtils, so how would the 4.x code base call AWSTypesMessageConverter when run in a custom runtime?
I just had a discussion with some of the AWS engineers and it all comes down to the fact that you are using AWS type that do not match the type of the request you are doing. For example if you are using LB then you would have to be mapping it to ApplicationLoadBalancerRequestEvent
, and if plain gateway, then APIGatewayV2HTTPEvent
.
Now. . . that does sound as very inconvenient thing to do and solution for that as you already pointed out is to use POJO or Spring Message
if you interested not only in the payload but also a metadata (i.e., headers) that comes with the request.
Anyway, i'll close this as the original issue is addressed. Feel free to raise a new one if you still believe there is a problem.
@olegz any update on when 3.2.7 will be released?
Describe the bug
I have a Spring Cloud Function application setup in AWS Lambda as a docker image. One of the function is defined as
Function<APIGatewayV2HTTPEvent, APIGatewayV2HTTPResponse>
. The lambda is behind an Application Load Balancer (ALB).When I send request to the load balancer, it is successfully routed to the function and is correctly invoked, however, the provided "body" is always removed before it is sent to my Function.
Here are some of the logs from AWS cloudwatch:
The above shows the request message has a body -
"body": "hi"
When I log the
APIGatewayV2HTTPEvent
that's provided to my cloud function, I get the below output:In the above, the payload has a null body. I looked through the AWSLambdaUtils and noticed the body is removed here and a new
MessageBuilder
is returned, however I'm unsure whether this piece is actually hit or working correctly.I've tested with multiple different input types to the function (string, Map<String, Object>, Message) and all results are the same. I've also tested this through the AWS console by sending an
api-gateway-aws-proxy
test event and the same thing happens.Sample
Here's the sample function:
I've attached a zip of a sample project as well as cloudwatch event logs.