Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write Java Lambda handler for API Gateway Websocket?

I'm having a hard time figuring out how to write a Java Lambda function that handles Websocket messages where the Websockets are handled by the new API Gateway function that was just released towards the end of 2018. Specific questions: * What type should I use for the input object? I'm currently using APIGatewayProxyRequestEvent. Is there a type specific to Websocket requests? I don't see one in aws-lambda-java-events-2.2.5.jar. * If I am using the correct type, how can I access the connection ID? Do I somehow need to use API Mapping? I saw this link but it doesn't actually tell you how to do the mapping for Websockets, which seem to have different options than REST APIs for this sort of thing. https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-mapping-template-reference.html

Thanks in advance!

public class WebsocketHandler implements RequestHandler {

@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
    context.getLogger().log("Input: " + input);
    context.getLogger().log("Context:  " + context);

    ProxyRequestContext requestContext = input.getRequestContext();
    context.getLogger().log("requestContext:  " + requestContext);

    // I don't see Connection ID in any of these

    APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
    response.setStatusCode(200);
    response.setBody("All good here.");
    return response;
}

}

like image 681
Joel Ezell Avatar asked Oct 16 '22 06:10

Joel Ezell


1 Answers

Here's the response that I got from AWS Support. It works! I haven't yet been able to send back towards the client though. If anybody has successfully done that, please let me know. I'm trying to use AmazonHTTPClient and it's not clear to me how to properly sign the message using AWS4Signer. If anybody has successfully done this, please let me know.

Currently, we don't offer support for web sockets in APIGatewayProxyRequestEvent as we do for REST [1]. However I have mentioned this to the team that looks after the GitHub repository, so they'll eventually implement a class for web socket too.

The alternative, at the moment, is to treat the input as a stream and parse it using any available JSON parser. To get you started I have attached a sample project that you can build with "mvn package" and upload to Lambda. I have tested it personally and I was able to print the whole requestContext [2] returned by API Gateway as a string. The only missing part is the parsing of the JSON string.

Please note that the code I provided comes from some examples I was able to gather internally and it's not ready for production, it is solely to be used as boilerplate code. Also I wish to mention that code support is usually out of scope for AWS Premium Support, so I cannot guarantee that either I or other AWS engineers will be able to support this code further. However I wanted to provide you with something to start with as I understand our documentation lacks examples of Web Socket API Gateway and Java.

CODE SAMPLE

package example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class LambdaBasicStreamFunction implements RequestStreamHandler {
    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        int letter;
        String eventObject = "";

        while ((letter = inputStream.read()) > -1) {
            char inputChar= (char) letter;
            eventObject += inputChar;
        }

        //Passing a custom response as the output string
        String response = "{\n" +
                "    \"statusCode\": 200,\n" +
                "    \"headers\": {\"Content-Type\": \"application/json\"},\n" +
                "    \"body\": \"plain text response\"\n" +
                "}";
        outputStream.write(response.getBytes());

        System.out.println("Input-Event: " + eventObject);
    }
}
like image 63
Joel Ezell Avatar answered Oct 21 '22 07:10

Joel Ezell