Repository: quarkusio/quarkus
Issue: Quarkus 2.10.0 doesn't work for Simulate Amazon Lambda Deployment with SAM CLI

### Describe the bug

With a simple app (e.g. Hello world REST API), Quarkus 2.9.2 allows me to simulate an AWS Lambda app using SAM CLI locally as below:

sam local start-api --template target/sam.jvm.yaml

But Quarkus 2.10.0 doesn't work with the error as the actual behavior. I know that Quarkus dev mode is good enough to test the function since Quarkus dev mode starts a mock AWS Lambda event server that will convert HTTP requests. But as long as we provide the sam CLI guide in our doc(https://quarkus.io/guides/amazon-lambda-http), sam local test should work too.

### Expected behavior

Start a Quarkus dev mode without an error then a developer can access the REST API to invoke the function.

### Actual behavior

I have the following error:

```
2022-06-27 17:18:36,102 ERROR [qua.ama.lam.http] (main) Request Failure: java.lang.ClassCastException: class lambdainternal.api.LambdaContext cannot be cast to class io.quarkus.amazon.lambda.runtime.AmazonLambdaContext (lambdainternal.api.LambdaContext is in unnamed module of loader 'app'; io.quarkus.amazon.lambda.runtime.AmazonLambdaContext is in unnamed module of loader lambdainternal.CustomerClassLoader @1a6c5a9e)
	at io.quarkus.amazon.lambda.http.LambdaHttpHandler.handleRequest(LambdaHttpHandler.java:70)
	at io.quarkus.amazon.lambda.http.LambdaHttpHandler.handleRequest(LambdaHttpHandler.java:47)
	at io.quarkus.amazon.lambda.runtime.AmazonLambdaRecorder.handle(AmazonLambdaRecorder.java:85)
	at io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler.handleRequest(QuarkusStreamHandler.java:58)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:375)
	at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:899)
	at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:268)
	at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:206)
	at lambdainternal.AWSLambda.main(AWSLambda.java:200)

END RequestId: 11f8a8d0-2db1-48b2-a39d-5e15caea30c9
REPORT RequestId: 11f8a8d0-2db1-48b2-a39d-5e15caea30c9	Init Duration: 0.16 ms	Duration: 3012.45 ms	Billed Duration: 3013 ms	Memory Size: 512 MB	Max Memory Used: 512 MB	
No Content-Type given. Defaulting to 'application/json'.
2022-06-27 13:18:36 127.0.0.1 - - [27/Jun/2022 13:18:36] "GET /hello/greeting/awslocal HTTP/1.1" 500 -
```

### How to Reproduce?

_No response_

### Output of `uname -a` or `ver`

Darwin Daniels-MacBook-Pro 21.5.0 Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:22 PDT 2022; root:xnu-8020.121.3~4/RELEASE_X86_64 x86_64

### Output of `java -version`

openjdk version "11.0.10" 2021-01-19 OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9) OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)

### GraalVM version (if different from Java)

_No response_

### Quarkus version or git rev

2.10.0.Final

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Apache Maven 3.8.4 

### Additional information

_No response_

Changed files:
extensions/amazon-lambda/common-runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaContext.java
extensions/amazon-lambda-http/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java
extensions/amazon-lambda-http/http-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockHttpEventServer.java
extensions/amazon-lambda-rest/rest-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockRestEventServer.java
extensions/amazon-lambda-rest/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java

diff --git a/extensions/amazon-lambda-http/http-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockHttpEventServer.java b/extensions/amazon-lambda-http/http-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockHttpEventServer.java
index 9ee81290fab..cd6bfb7308c 100644
--- a/extensions/amazon-lambda-http/http-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockHttpEventServer.java
+++ b/extensions/amazon-lambda-http/http-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockHttpEventServer.java
@@ -56,6 +56,7 @@ public void handleHttpRequests(RoutingContext ctx) {
         event.setRequestContext(new APIGatewayV2HTTPEvent.RequestContext());
         event.getRequestContext().setHttp(new APIGatewayV2HTTPEvent.RequestContext.Http());
         event.getRequestContext().getHttp().setMethod(ctx.request().method().name());
+        event.getRequestContext().getHttp().setSourceIp(ctx.request().connection().remoteAddress().hostAddress());
         event.setRawPath(ctx.request().path());
         event.setRawQueryString(ctx.request().query());
         for (String header : ctx.request().headers().names()) {
diff --git a/extensions/amazon-lambda-http/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java b/extensions/amazon-lambda-http/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java
index 765e31a7e29..53294384a01 100644
--- a/extensions/amazon-lambda-http/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java
+++ b/extensions/amazon-lambda-http/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java
@@ -4,7 +4,6 @@
 
 import java.io.ByteArrayOutputStream;
 import java.net.InetSocketAddress;
-import java.net.URL;
 import java.nio.channels.Channels;
 import java.nio.channels.WritableByteChannel;
 import java.nio.charset.StandardCharsets;
@@ -36,7 +35,6 @@
 import io.netty.handler.codec.http.HttpVersion;
 import io.netty.handler.codec.http.LastHttpContent;
 import io.netty.util.ReferenceCountUtil;
-import io.quarkus.amazon.lambda.runtime.AmazonLambdaContext;
 import io.quarkus.netty.runtime.virtual.VirtualClientConnection;
 import io.quarkus.netty.runtime.virtual.VirtualResponseHandler;
 import io.quarkus.vertx.http.runtime.QuarkusHttpHeaders;
@@ -67,7 +65,7 @@ public APIGatewayV2HTTPResponse handleRequest(APIGatewayV2HTTPEvent request, Con
         }
 
         try {
-            return nettyDispatch(clientAddress, request, (AmazonLambdaContext) context);
+            return nettyDispatch(clientAddress, request, context);
         } catch (Exception e) {
             log.error("Request Failure", e);
             APIGatewayV2HTTPResponse res = new APIGatewayV2HTTPResponse();
@@ -168,7 +166,7 @@ public void close() {
     }
 
     private APIGatewayV2HTTPResponse nettyDispatch(InetSocketAddress clientAddress, APIGatewayV2HTTPEvent request,
-            AmazonLambdaContext context)
+            Context context)
             throws Exception {
         QuarkusHttpHeaders quarkusHeaders = new QuarkusHttpHeaders();
         quarkusHeaders.setContextObject(Context.class, context);
@@ -223,12 +221,19 @@ httpMethod, ofNullable(request.getRawQueryString())
         NettyResponseHandler handler = new NettyResponseHandler(request);
         VirtualClientConnection connection = VirtualClientConnection.connect(handler, VertxHttpRecorder.VIRTUAL_HTTP,
                 clientAddress);
-        if (connection.peer().remoteAddress().equals(VertxHttpRecorder.VIRTUAL_HTTP)) {
-            URL requestURL = context.getRequestURL();
+        if (request.getRequestContext() != null
+                && request.getRequestContext().getHttp() != null
+                && request.getRequestContext().getHttp().getSourceIp() != null
+                && request.getRequestContext().getHttp().getSourceIp().length() > 0) {
+            int port = 443; // todo, may be bad to assume 443?
+            if (request.getHeaders() != null &&
+                    request.getHeaders().get("X-Forwarded-Port") != null) {
+                port = Integer.parseInt(request.getHeaders().get("X-Forwarded-Port"));
+            }
             connection.peer().attr(ConnectionBase.REMOTE_ADDRESS_OVERRIDE).set(
-                    SocketAddress.inetSocketAddress(requestURL.getPort(), requestURL.getHost()));
+                    SocketAddress.inetSocketAddress(port,
+                            request.getRequestContext().getHttp().getSourceIp()));
         }
-
         connection.sendMessage(nettyRequest);
         connection.sendMessage(requestContent);
         try {
diff --git a/extensions/amazon-lambda-rest/rest-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockRestEventServer.java b/extensions/amazon-lambda-rest/rest-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockRestEventServer.java
index b19ed5d533b..9b2a6e684b6 100644
--- a/extensions/amazon-lambda-rest/rest-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockRestEventServer.java
+++ b/extensions/amazon-lambda-rest/rest-event-server/src/main/java/io/quarkus/amazon/lambda/runtime/MockRestEventServer.java
@@ -16,6 +16,7 @@
 import com.fasterxml.jackson.databind.ObjectReader;
 import com.fasterxml.jackson.databind.ObjectWriter;
 
+import io.quarkus.amazon.lambda.http.model.ApiGatewayRequestIdentity;
 import io.quarkus.amazon.lambda.http.model.AwsProxyRequest;
 import io.quarkus.amazon.lambda.http.model.AwsProxyRequestContext;
 import io.quarkus.amazon.lambda.http.model.AwsProxyResponse;
@@ -61,6 +62,8 @@ public void handleHttpRequests(RoutingContext ctx) {
         event.setRequestContext(new AwsProxyRequestContext());
         event.getRequestContext().setRequestId(requestId);
         event.getRequestContext().setHttpMethod(ctx.request().method().name());
+        event.getRequestContext().setIdentity(new ApiGatewayRequestIdentity());
+        event.getRequestContext().getIdentity().setSourceIp(ctx.request().connection().remoteAddress().hostAddress());
         event.setHttpMethod(ctx.request().method().name());
         event.setPath(ctx.request().path());
         if (ctx.request().query() != null) {
diff --git a/extensions/amazon-lambda-rest/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java b/extensions/amazon-lambda-rest/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java
index 9a3fe62c13d..bb8c1b576e4 100644
--- a/extensions/amazon-lambda-rest/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java
+++ b/extensions/amazon-lambda-rest/runtime/src/main/java/io/quarkus/amazon/lambda/http/LambdaHttpHandler.java
@@ -2,7 +2,6 @@
 
 import java.io.ByteArrayOutputStream;
 import java.net.InetSocketAddress;
-import java.net.URL;
 import java.net.URLEncoder;
 import java.nio.channels.Channels;
 import java.nio.channels.WritableByteChannel;
@@ -34,7 +33,6 @@
 import io.quarkus.amazon.lambda.http.model.AwsProxyRequestContext;
 import io.quarkus.amazon.lambda.http.model.AwsProxyResponse;
 import io.quarkus.amazon.lambda.http.model.Headers;
-import io.quarkus.amazon.lambda.runtime.AmazonLambdaContext;
 import io.quarkus.netty.runtime.virtual.VirtualClientConnection;
 import io.quarkus.netty.runtime.virtual.VirtualResponseHandler;
 import io.quarkus.vertx.http.runtime.QuarkusHttpHeaders;
@@ -62,7 +60,7 @@ public AwsProxyResponse handleRequest(AwsProxyRequest request, Context context)
         }
 
         try {
-            return nettyDispatch(clientAddress, request, (AmazonLambdaContext) context);
+            return nettyDispatch(clientAddress, request, context);
         } catch (Exception e) {
             log.error("Request Failure", e);
             return new AwsProxyResponse(500, errorHeaders, "{ \\"message\\": \\"Internal Server Error\\" }");
@@ -152,7 +150,7 @@ public void close() {
     }
 
     private AwsProxyResponse nettyDispatch(InetSocketAddress clientAddress, AwsProxyRequest request,
-            AmazonLambdaContext context)
+            Context context)
             throws Exception {
         String path = request.getPath();
         //log.info("---- Got lambda request: " + path);
@@ -210,10 +208,17 @@ private AwsProxyResponse nettyDispatch(InetSocketAddress clientAddress, AwsProxy
         NettyResponseHandler handler = new NettyResponseHandler(request);
         VirtualClientConnection connection = VirtualClientConnection.connect(handler, VertxHttpRecorder.VIRTUAL_HTTP,
                 clientAddress);
-        if (connection.peer().remoteAddress().equals(VertxHttpRecorder.VIRTUAL_HTTP)) {
-            URL requestURL = context.getRequestURL();
+        if (request.getRequestContext() != null
+                && request.getRequestContext().getIdentity() != null
+                && request.getRequestContext().getIdentity().getSourceIp() != null
+                && request.getRequestContext().getIdentity().getSourceIp().length() > 0) {
+            int port = 443; // todo, may be bad to assume 443?
+            if (request.getMultiValueHeaders() != null &&
+                    request.getMultiValueHeaders().getFirst("X-Forwarded-Port") != null) {
+                port = Integer.parseInt(request.getMultiValueHeaders().getFirst("X-Forwarded-Port"));
+            }
             connection.peer().attr(ConnectionBase.REMOTE_ADDRESS_OVERRIDE).set(
-                    SocketAddress.inetSocketAddress(requestURL.getPort(), requestURL.getHost()));
+                    SocketAddress.inetSocketAddress(port, request.getRequestContext().getIdentity().getSourceIp()));
         }
 
         connection.sendMessage(nettyRequest);
diff --git a/extensions/amazon-lambda/common-runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaContext.java b/extensions/amazon-lambda/common-runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaContext.java
index 02b006d9024..946bcb46f3a 100644
--- a/extensions/amazon-lambda/common-runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaContext.java
+++ b/extensions/amazon-lambda/common-runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaContext.java
@@ -13,7 +13,6 @@
 
 import java.io.IOException;
 import java.net.HttpURLConnection;
-import java.net.URL;
 
 import com.amazonaws.services.lambda.runtime.ClientContext;
 import com.amazonaws.services.lambda.runtime.CognitoIdentity;
@@ -35,7 +34,6 @@ public class AmazonLambdaContext implements Context {
     private long runtimeDeadlineMs = 0;
     private final int memoryLimitInMB;
     private final LambdaLogger logger;
-    private final URL requestURL;
 
     public AmazonLambdaContext(HttpURLConnection request, ObjectReader cognitoReader, ObjectReader clientCtxReader)
             throws IOException {
@@ -64,7 +62,6 @@ public AmazonLambdaContext(HttpURLConnection request, ObjectReader cognitoReader
             runtimeDeadlineMs = Long.valueOf(runtimeDeadline);
         }
         logger = LambdaRuntime.getLogger();
-        requestURL = request.getURL();
     }
 
     @Override
@@ -121,8 +118,4 @@ public int getMemoryLimitInMB() {
     public LambdaLogger getLogger() {
         return logger;
     }
-
-    public URL getRequestURL() {
-        return requestURL;
-    }
 }