Websocket con API Gateway y AWS Lambda

En el siguiente código muestro como utilizar Java para crear un Lambda de AWS que permite utilizar Web Socket desde API Gateway.

  1. public class WebSocketLambda implements RequestStreamHandler {
  2. private static final AWSCredentials CREDENCIALES
  3. = new EnvironmentVariableCredentialsProvider().getCredentials();
  4. @Override
  5. public void handleRequest(InputStream in, OutputStream out, Context cntxt) throws IOException {
  6. // obtenemos la representación como JSON del request generado por aws
  7. JsonObject json = Json.createReader(in).readObject();
  8. if (json.getJsonObject("requestContext").getString("routeKey").equals("$default")) {
  9. final String payload = json.getString("body"); // contenido que el cliente nos envia
  10. Request request = new DefaultRequest<>("execute-api");
  11. request.setHttpMethod(HttpMethodName.POST);
  12. request.setEndpoint(URI.create(new StringBuilder()
  13. .append(System.getenv("url_api")) // el API gateway la define
  14. .append("/")
  15. // identificador del cliente al que le respondemos
  16. .append(json.getJsonObject("requestContext").getString("connectionId"))
  17. .toString()));
  18. // escribimos el mismo mensaje que el cliente nos envía
  19. request.setContent(new ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8)));
  20. AWS4Signer signer = new AWS4Signer();
  21. signer.setServiceName(request.getServiceName());
  22. signer.sign(request, CREDENCIALES);
  23. // enviar request al api gateway
  24. new AmazonHttpClient(new ClientConfiguration())
  25. .requestExecutionBuilder()
  26. .executionContext(new ExecutionContext(true))
  27. .request(request)
  28. .errorResponseHandler(new HttpResponseHandler() {
  29. @Override
  30. public AmazonClientException handle(HttpResponse rsp) throws Exception {
  31. return new AmazonClientException(
  32. new StringBuilder()
  33. .append("error al enviar mensaje")
  34. .append(System.getenv("url_api"))
  35. .append(rsp.getStatusCode())
  36. .append(rsp.getStatusText())
  37. .append(leerError(rsp.getContent())).toString());
  38. }
  39. @Override
  40. public boolean needsConnectionLeftOpen() {
  41. return false;
  42. }
  43. }).execute(new HttpResponseHandler() {
  44. @Override
  45. public Void handle(HttpResponse response) {
  46. return null;
  47. }
  48. @Override
  49. public boolean needsConnectionLeftOpen() {
  50. return false;
  51. }
  52. });
  53. }
  54. try (PrintWriter pw = new PrintWriter(out)) {
  55. JsonObject response = Json.createObjectBuilder()
  56. .add("statusCode", 200)
  57. .build();
  58. pw.write(response.toString());
  59. }
  60. }
  61. private static String leerError(InputStream inputStream) throws IOException {
  62. final ByteArrayOutputStream bos = new ByteArrayOutputStream();
  63. byte[] buffer = new byte[1024];
  64. int length;
  65. while ((length = inputStream.read(buffer)) != -1) {
  66. bos.write(buffer, 0, length);
  67. }
  68. return bos.toString(StandardCharsets.UTF_8.name());
  69. }
  70. }


Algunas notas sobre el código:

  • Recibe conexiones y responde el mismo mensaje recibido al cliente utilizando la URL que entrega el API Gateway.
  • La URL Connection que entrega el API Gateway se define como variable de ambiente (url_api).
  • En connectionId esta definido el identificador del cliente entregado por AWS.


En github he dejado el ejemplo completo utilizando maven para construirlo y algunos comentarios adicionales sobre la configuración en AWS.

Algunos enlaces MUY útiles para conocer los Web Sockets en API Gateway:




No hay comentarios.:

Publicar un comentario