使用AWS SDK调用Lambda Function URL时触发NullPointerException
Java调用Lambda Function URL签名失败问题排查
我正尝试在Java应用中通过Function URL调用AWS Lambda函数,使用Java AWS SDK 2.18.7对请求进行签名,但始终无法成功。我拥有具备Lambda Function URL执行权限的用户的访问密钥和秘密密钥。
代码在第150行Response awsResponse = reb.execute();处崩溃,代码如下:
Request<Void> request = new DefaultRequest<Void>("lambda"); request.setHttpMethod(HttpMethodName.POST); request.setEndpoint(URI.create(this.LAMBDA_URL)); request.setContent(new ByteArrayInputStream(postJsonString.getBytes(StandardCharsets.UTF_8))); Map<String, String> headers = new HashMap<String, String>(); headers.put("Content-Length", Integer.toString(postJsonString.length())); request.setHeaders(headers); // Sign AWS Request AWS4Signer signer = new AWS4Signer(); signer.setRegionName(MY_REGION); signer.setServiceName(request.getServiceName()); BasicAWSCredentials awsCreds = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY); signer.sign(request, awsCreds); // Execute and get response ClientConfiguration config = new ClientConfiguration(); AmazonHttpClient client = new AmazonHttpClient(config); RequestExecutionBuilder reb = client.requestExecutionBuilder(); reb = reb.request(request); reb = reb.executionContext(new ExecutionContext()); Response<Void> awsResponse = reb.execute();
控制台输出的异常信息:
Exception in thread "main" java.lang.NullPointerException at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1879) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1418) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1387) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1157) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:814) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:781) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:755) at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:715) at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:697) at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:702) at aws_auth_awssdk2_18_7.Main.aws_sdk_attemp(Main.java:150) at aws_auth_awssdk2_18_7.Main.main(Main.java:67)
问题根源与修复方案
SDK版本混淆
你使用的是AWS SDK v2的版本号,但代码全是v1的API(DefaultRequest、AWS4Signer、AmazonHttpClient等),v1和v2的API完全不兼容,这是核心问题。必须统一使用v2的规范实现。缺失必要请求头
Lambda Function URL要求请求携带Content-Type: application/json头,你当前代码未设置,会导致请求被拒绝,进而触发错误响应处理时的空指针异常。修正后的v2代码示例
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.signer.Aws4Signer; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; import java.io.InputStream; import java.net.URI; import java.util.HashMap; import java.util.Map; public class LambdaUrlCaller { private static final String LAMBDA_URL = "你的Function URL"; private static final String ACCESS_KEY = "你的访问密钥"; private static final String SECRET_KEY = "你的秘密密钥"; private static final Region REGION = Region.of("你的区域"); public static void main(String[] args) { String postJson = "{\"test\": \"data\"}"; // 构建请求头 Map<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); // 构建未签名请求 SdkHttpFullRequest.Builder requestBuilder = SdkHttpFullRequest.builder() .method(SdkHttpMethod.POST) .uri(URI.create(LAMBDA_URL)) .headers(headers) .contentStreamProvider(() -> SdkBytes.fromUtf8String(postJson).asInputStream()); // 签名请求 Aws4Signer signer = Aws4Signer.create(); SdkHttpFullRequest signedRequest = signer.sign( requestBuilder.build(), Aws4Signer.builder() .credentials(AwsBasicCredentials.create(ACCESS_KEY, SECRET_KEY)) .region(REGION) .serviceName("lambda") .build() ); // 执行请求并处理响应 try (UrlConnectionHttpClient client = UrlConnectionHttpClient.create()) { software.amazon.awssdk.http.HttpResponse response = client.execute(signedRequest); System.out.println("响应状态码: " + response.statusCode()); // 读取响应内容 InputStream responseStream = response.contentStreamProvider().get(); // 处理响应流逻辑... } catch (Exception e) { e.printStackTrace(); } } }
额外注意事项
- 确认Lambda Function URL的认证类型设置为
AWS_IAM,否则签名会被忽略或拒绝。 - 确保IAM用户的权限策略包含
lambda:InvokeFunctionUrl,并指定正确的Function ARN。 - v2 SDK会自动处理
Content-Length,无需手动计算,避免编码不一致导致的长度错误。
内容的提问来源于stack exchange,提问作者benino
相关产品推荐
相关产品推荐

