首页 > 解决方案 > AWS 无服务器请求 - JSON 正文/httpMethod 始终为空

问题描述

当我发送 POST 请求时,我从input.getBody()input.getHttpMethod()获得 NullPointerException 。我没有定义映射模板 -默认情况下,它设置为当没有模板与请求 Content-Type 标头匹配时。

我的 POST 请求

{
    "shiftStart": "22/02/2021 18:00:00",
    "shiftEnd": "22/02/2021 19:00:00",
    "employee": {
        "id": "6",
        "firstName": "Joe",
        "lastName": "Brown"
    }
}

一旦我得到这个异常,它看起来像input.getHttpMethod()传递了一次:

{
    "errorMessage": "BODY",
    "errorType": "java.lang.NullPointerException",
    "stackTrace": [
        "helloworld.App.handleRequest(App.java:48)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/java.lang.reflect.Method.invoke(Unknown Source)"
    ]
}

但我没有改变任何东西,现在我得到以下异常:

{
    "errorMessage": "java.lang.NullPointerException",
    "errorType": "java.lang.NullPointerException",
    "stackTrace": [
        "helloworld.App.handleRequest(App.java:41)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
        "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)",
        "java.base/java.lang.reflect.Method.invoke(Unknown Source)"
    ]
}

我的课程:

public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    @Override
    public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("X-Custom-Header", "application/json");

        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
                .withHeaders(headers);

        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient();
        DynamoDBMapper mapper = new DynamoDBMapper(client);

        Shift shift;
        String output;

        if (input.getHttpMethod().equalsIgnoreCase(HttpMethod.GET.name())) {
            shift = mapper.load(Shift.class, context.getAwsRequestId());
            if (shift == null) {
                throw new ResourceNotFoundException("Resource not found");
            }
            output = shift.toString();
        } else if (input.getHttpMethod().equalsIgnoreCase(HttpMethod.POST.name())) {
            if (input.getBody() == null) throw new NullPointerException("BODY");
            shift = new Shift(input.getBody());
            WorkSchedule workSchedule = new WorkSchedule(client);
            if (!workSchedule.isShiftPossible(shift)) {
                throw new ConditionalCheckFailedException("Conditional check failed");
            }
            mapper.save(shift);
            output = "SHIFT SAVED";
        } else {
            output = "Unsupported operation";
        }

        return response
                .withStatusCode(200)
                .withBody(output);
    }
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@DynamoDBTable(tableName = "WORK_SCHEDULE")
public class Shift {

    public Shift(String json) {
        Gson gson = new Gson();
        Shift request = gson.fromJson(json, Shift.class);
        this.id = request.getId();
        this.shiftStart = request.getShiftStart();
        this.shiftEnd = request.getShiftEnd();
        this.employee = request.getEmployee();
    }

    @DynamoDBHashKey
    @DynamoDBAutoGeneratedKey
    private String id;

    @DynamoDBAttribute
    private String shiftStart;

    @DynamoDBAttribute
    private String shiftEnd;

    @DynamoDBAttribute
    private Employee employee;

    @Override
    public String toString() {
        return "Shift{" +
                "id='" + id + '\'' +
                ", shiftStart='" + shiftStart + '\'' +
                ", shiftEnd='" + shiftEnd + '\'' +
                ", employee=" + employee +
                '}';
    }
}
@Getter
@Setter
@AllArgsConstructor
@DynamoDBDocument
public class Employee {

    private String id;
    private String firstName;
    private String lastName;

    @Override
    public String toString() {
        return "Employee{" +
                "id='" + id + '\'' +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }
}

标签: javaamazon-web-servicesresthttpaws-lambda

解决方案


Api Gateway 有两种基本类型的 Lambda 集成 LAMBDA 和 LAMBDA_PROXY。

常规 LAMBDA 将按原样通过请求正文。

如果我们Use Lambda Proxy integration在集成请求中启用,它将是 LAMBDA_PROXY,这将通过包装额外的细节(如 queryParms、Api Keys、Http Headers、方法类型等)来传递请求,这些细节可以序列化到APIGatewayProxyRequestEvent类中。

queryStringParameters使用 queryParms。

body以 Json 正文为字符串。

pathParameters带有路径参数。

所以,在这种情况下,我们只需要启用Use Lambda Proxy integration


推荐阅读