SparkJava request.body() consumes payload in first defined before() filter

オープン
#373 コメント 2 件 リアクション 1 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
25/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
aws, java, spark
領域
api, backend, cloud

調査の方向性

build.gradle と RequestStreamLambdaHandler.java から始め、Spark コンテナのバージョン 1.3.1 と 1.5.1 でその main メソッドを実行して、異なるログを再現します。SparkLambdaContainerHandler.proxyStream とリクエストボディの処理を追跡し、すべての before フィルターとハンドラーで request.body() がペイロードを返すようになった時点で issue の対応完了とします。

索引モデルが issue の本文から書いたものです。

説明

enhancement need feedback

To help us debug your issue fill in the basic information below using the options provided

Serverless Java Container version: 1.5.1

Implementations: Spark

Framework version: 2.9.2

Frontend service: REST API

Deployment method: Lambda, Request is sent with AwsProxyRequest

Scenario

Previously we were using combination : SparkJava 2.9.2 + AwsServerless 1.3.1 and everything was working fine.
Just few days ago we tried to upgrade AwsServerless to 1.5.1 and noticed that POST works incorrectly.

Expected behavior

request.body() should be available for getting any number of times in filters, handlers.
It was working fine in 1.3.1

Actual behavior

request.body() returns value only in first specified filter. Then it returns "" (empty String)
It stopped working after we updated to 1.5.1

Steps to reproduce

To reproduce the issue, simply run RequestStreamLambdaHandler.main() with no any prerequisites.
Just check the version in build.gradle before debug.

apply plugin: 'java'
apply plugin: 'idea'

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.sparkjava:spark-core:2.9.2'
    //compile 'com.amazonaws.serverless:aws-serverless-java-container-spark:1.3.1'
    compile 'com.amazonaws.serverless:aws-serverless-java-container-spark:1.5.1'
}

RequestStreamLambdaHandler.java

package hello;

import com.amazonaws.serverless.exceptions.ContainerInitializationException;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
import com.amazonaws.serverless.proxy.spark.SparkLambdaContainerHandler;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;

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

import spark.Request;
import spark.Response;
import spark.Spark;

import static spark.Spark.before;
import static spark.Spark.post;

public class RequestStreamLambdaHandler implements RequestStreamHandler {
    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        SparkLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
        try {
                handler = SparkLambdaContainerHandler.getAwsProxyHandler();
                defineBaseResources();                
                Spark.awaitInitialization();
            } catch (ContainerInitializationException e) {
                return;
            }

        handler.proxyStream(inputStream, outputStream, context);
    }

    public void defineBaseResources() {
        // define base routes
        before("/*", this::beforeFilter1);
        before("/*", this::beforeFilter2);
        before("/*", this::beforeFilter3);
        
        post("/post-request", this::handlePost);        
    }

    private Request handlePost(Request req, Response res) {
        System.out.println("POST Handler Request Body: " + req.body());
        return req;
    }

    protected void beforeFilter1(Request req, Response res) {
        System.out.println("Filter 1 Request Body: " + req.body());
    }

    protected void beforeFilter2(Request req, Response res) {
        System.out.println("Filter 2 Request Body: " + req.body());
    }

    protected void beforeFilter3(Request req, Response res) {
        System.out.println("Filter 3 Request Body: " + req.body());
    }

    public static void main(String[] args) throws Exception {
        String body = "{\"path\": \"/post-request\","
                + "    \"httpMethod\": \"POST\","
                + "    \"requestContext\": {"
                + "        \"identity\": {}"              
                + "    },"
                + "    \"body\":\"{\\\"field1\\\":\\\"value1\\\"}\""                
                + "}";
        
        
        RequestStreamLambdaHandler handler = new RequestStreamLambdaHandler();
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        handler.handleRequest(new ByteArrayInputStream(body.getBytes()), baos, null);
    }
}

Full log output

Paste the full log output from the Lambda function's CloudWatch logs

Log while 1.3.1 is used :

> Task :RequestStreamLambdaHandler.main()
Filter 1 Request Body: {"field1":"value1"}
Filter 2 Request Body: {"field1":"value1"}
Filter 3 Request Body: {"field1":"value1"}
POST Handler Request Body: {"field1":"value1"}

Log while 1.5.1 is used :

> Task :RequestStreamLambdaHandler.main()
Filter 1 Request Body: {"field1":"value1"}
Filter 2 Request Body: 
Filter 3 Request Body: 
POST Handler Request Body: 
主要言語
Java
スター
1.6k
フォーク
575
平均マージ
1日 15時間
マージ済み PR(30日)
12

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

aws/serverless-java-container のほかの issue

aws/serverless-java-container の issue をすべて見る

似ている issue

Java の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。