2018年7月24日 星期二

[Java] JAX-RS on AWS Lambda

AWS Lambda 有提供 proxy framework 掛上 jersey。 首先加上依賴包,

// build.gradle
dependencies {
    compile (
        'com.amazonaws.serverless:aws-serverless-java-container-jersey:1.1.3',
        'org.glassfish.jersey.media:jersey-media-json-jackson:2.27',
        'org.glassfish.jersey.inject:jersey-hk2:2.27'
    )
}

然後接口要換掉 (RequestHandler -> RequestStreamHandler),

package example;

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

import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;

import com.amazonaws.serverless.proxy.jersey.JerseyLambdaContainerHandler;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;

public final class ProxyWithStream implements RequestStreamHandler {

    private static final ResourceConfig jerseyApplication = new ResourceConfig()
            .packages("<PACKAGE-NAME>")
            .register(JacksonFeature.class);

    private static final JerseyLambdaContainerHandler handler = JerseyLambdaContainerHandler
            .getAwsProxyHandler(jerseyApplication);

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        handler.stripBasePath("<API-GATEWAY-PATH>");
        handler.proxyStream(inputStream, outputStream, context);
        outputStream.close();
    }

}
其中 <PACKAGE-NAME> 要輸入 resource 路徑, <API-GATEWAY-PATH> 則是端視在 API Gateway 的設定。 假設 API Gateway 設定 "/v1/foo/{proxy+}", JAX-RS 設定 APIs 為 "/bar/{id}", <API-GATEWAY-PATH> 就要設定為 "/v1/foo"。

接下來 Lambda 測試的 payload 需要更改成 API Gateway 傳給 Lambda 的格式,然後就可以測試了。

{
  "body": "",  // POST/PUT/PATCH body 的來源
  "resource": "/{proxy+}",
  "requestContext": {
    "resourceId": "123456",
    "apiId": "1234567890",
    "resourcePath": "/{proxy+}",
    "httpMethod": "GET",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "accountId": "123456789012",
    "identity": {
      "apiKey": null,
      "userArn": null,
      "cognitoAuthenticationType": null,
      "caller": null,
      "userAgent": "Custom User Agent String",
      "user": null,
      "cognitoIdentityPoolId": null,
      "cognitoIdentityId": null,
      "cognitoAuthenticationProvider": null,
      "sourceIp": "127.0.0.1",
      "accountId": null
    },
    "stage": "prod"
  },
  "queryStringParameters": {
    "fields": "name"  // query parameters 的來源
  },
  "headers": {
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "Accept-Language": "en-US,en;q=0.8",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "User-Agent": "Custom User Agent String",
    "Accept-Encoding": "gzip, deflate, sdch"
  },
  "pathParameters": {
    "proxy": "bar/12345"
  },
  "httpMethod": "GET",  // method 的來源
  "stageVariables": {},
  "path": "/v1/foo/bar/12345"  // url mapping 的來源
}

參考資料:

系列:

1 則留言:

[Java] Invalid HTTP method: PATCH

最近系統需要使用 Netty4,所以把衝突的 Netty3 拆掉,然後就出現了例外。 pom.xml <dependency> <groupId>com.ning</groupId> <artifactId>as...