All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClient Maven / Gradle / Ivy

There is a newer version: 2.6.0
Show newest version
package com.amazonaws.services.lambda.runtime.api.client.runtimeapi;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static java.net.HttpURLConnection.HTTP_ACCEPTED;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * LambdaRuntimeClient is a client of the AWS Lambda Runtime HTTP API for custom runtimes.
 * 

* API definition can be found at https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html *

* Copyright (c) 2019 Amazon. All rights reserved. */ public class LambdaRuntimeClient { private final String hostname; private final int port; private final String invocationEndpoint; private static final String DEFAULT_CONTENT_TYPE = "application/json"; private static final String XRAY_ERROR_CAUSE_HEADER = "Lambda-Runtime-Function-XRay-Error-Cause"; private static final String ERROR_TYPE_HEADER = "Lambda-Runtime-Function-Error-Type"; private static final int XRAY_ERROR_CAUSE_MAX_HEADER_SIZE = 1024 * 1024; // 1MiB public LambdaRuntimeClient(String hostnamePort) { Objects.requireNonNull(hostnamePort, "hostnamePort cannot be null"); String[] parts = hostnamePort.split(":"); this.hostname = parts[0]; this.port = Integer.parseInt(parts[1]); this.invocationEndpoint = invocationEndpoint(); NativeClient.init(); } public InvocationRequest waitForNextInvocation() { return NativeClient.next(); } public void postInvocationResponse(String requestId, byte[] response) { NativeClient.postInvocationResponse(requestId.getBytes(UTF_8), response); } public void postInvocationError(String requestId, byte[] errorResponse, String errorType) throws IOException { postInvocationError(requestId, errorResponse, errorType, null); } public void postInvocationError(String requestId, byte[] errorResponse, String errorType, String errorCause) throws IOException { String endpoint = invocationErrorEndpoint(requestId); post(endpoint, errorResponse, errorType, errorCause); } public void getRestoreNext() throws IOException { doGet(restoreNextEndpoint(), HTTP_OK); } public int postRestoreError(byte[] errorResponse, String errorType) throws IOException { String endpoint = restoreErrorEndpoint(); return postError(endpoint, errorResponse, errorType, null); } public void postInitError(byte[] errorResponse, String errorType) throws IOException { String endpoint = initErrorEndpoint(); post(endpoint, errorResponse, errorType, null); } private void post(String endpoint, byte[] errorResponse, String errorType, String errorCause) throws IOException { URL url = createUrl(endpoint); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", DEFAULT_CONTENT_TYPE); if (errorType != null && !errorType.isEmpty()) { conn.setRequestProperty(ERROR_TYPE_HEADER, errorType); } if (errorCause != null && errorCause.getBytes().length < XRAY_ERROR_CAUSE_MAX_HEADER_SIZE) { conn.setRequestProperty(XRAY_ERROR_CAUSE_HEADER, errorCause); } conn.setFixedLengthStreamingMode(errorResponse.length); conn.setDoOutput(true); try (OutputStream outputStream = conn.getOutputStream()) { outputStream.write(errorResponse); } int responseCode = conn.getResponseCode(); if (responseCode != HTTP_ACCEPTED) { throw new LambdaRuntimeClientException(endpoint, responseCode); } // don't need to read the response, close stream to ensure connection re-use closeQuietly(conn.getInputStream()); } private String invocationEndpoint() { return getBaseUrl() + "/2018-06-01/runtime/invocation/"; } private String invocationErrorEndpoint(String requestId) { return invocationEndpoint + requestId + "/error"; } private String initErrorEndpoint() { return getBaseUrl() + "/2018-06-01/runtime/init/error"; } private String restoreErrorEndpoint() { return getBaseUrl() + "/2018-06-01/runtime/restore/error"; } private String restoreNextEndpoint() { return getBaseUrl() + "/2018-06-01/runtime/restore/next"; } private String getBaseUrl() { return "http://" + hostname + ":" + port; } private int postError(String endpoint, byte[] errorResponse, String errorType, String errorCause) throws IOException { Map headers = new HashMap<>(); if (errorType != null && !errorType.isEmpty()) { headers.put(ERROR_TYPE_HEADER, errorType); } if (errorCause != null && errorCause.getBytes().length < XRAY_ERROR_CAUSE_MAX_HEADER_SIZE) { headers.put(XRAY_ERROR_CAUSE_HEADER, errorCause); } return doPost(endpoint, DEFAULT_CONTENT_TYPE, headers, errorResponse); } private int doPost(String endpoint, String contentType, Map headers, byte[] payload) throws IOException { URL url = createUrl(endpoint); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", contentType); for (Map.Entry header : headers.entrySet()) { conn.setRequestProperty(header.getKey(), header.getValue()); } conn.setFixedLengthStreamingMode(payload.length); conn.setDoOutput(true); try (OutputStream outputStream = conn.getOutputStream()) { outputStream.write(payload); } // get response code before closing the stream int responseCode = conn.getResponseCode(); // don't need to read the response, close stream to ensure connection re-use closeInputStreamQuietly(conn); return responseCode; } private void doGet(String endpoint, int expectedHttpResponseCode) throws IOException { URL url = createUrl(endpoint); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); int responseCode = conn.getResponseCode(); if (responseCode != expectedHttpResponseCode) { throw new LambdaRuntimeClientException(endpoint, responseCode); } closeInputStreamQuietly(conn); } private URL createUrl(String endpoint) { try { return new URL(endpoint); } catch (MalformedURLException e) { throw new RuntimeException(e); } } private void closeQuietly(InputStream inputStream) { if (inputStream == null) return; try { inputStream.close(); } catch (IOException e) { } } private void closeInputStreamQuietly(HttpURLConnection conn) { InputStream inputStream; try { inputStream = conn.getInputStream(); } catch (IOException e) { return; } if (inputStream == null) { return; } try { inputStream.close(); } catch (IOException e) { // ignore } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy