Сбой ответов JSON Java сжатого Lambda JSON: «Не удалось выполнить из-за ошибки конфигурации: неправильный ответ Lambda прокси» - PullRequest
2 голосов
/ 27 апреля 2019

Я вызываю функцию AWS Lambda из шлюза AWS API. Возвращенный JSON необходимо сжать, поскольку он иногда становится слишком большим (слишком большой размер тела и т. Д.). Однако у меня есть некоторые проблемы при получении ответа через API-шлюз. Это мой код Java:

    @Override
    public JSONObject handleRequest(Object input, Context context) {
        String json_string = "";
        try {
            Gson gson = new Gson();
            json_string = gson.toJson(input, LinkedHashMap.class);
        } catch (ClassCastException ex) {
            json_string = (String) input;
        }

        GenerateJson generateJson = new GenerateJson ();
        String body = "";
        try {
            JSONParser parser = new JSONParser();
            Object jsonObj = parser.parse(json_string);
            JSONObject matchesobj = (JSONObject) jsonObj;

            if (matchesobj.containsKey("body")) {
                body = (String) matchesobj.get("body");
            } else {
                JSONObject error = new JSONObject();
                error.put("error", "No body with Base64 data in Request.");
                System.out.println(error.toJSONString());
                return error;
            }

        } catch (ParseException ex) {
            ex.printStackTrace();
        }

        byte[] decodedBytes = Base64.getDecoder().decode(body);
        String decodedString = new String(decodedBytes);
        // System.out.println(decodedString);

        JSONObject json = generateJson .getJson(decodedString, "", 2);

        JSONObject returnObject = new JSONObject();
        JSONObject headers = new JSONObject();
        returnObject.put("statusCode", 205);
        returnObject.put("isBase64Encoded", true);
        // returnObject.put("Content-Encoding", "gzip");

        returnObject.put("headers", headers);
        returnObject.put("body", compressStringAndReturnBase64(json.toString()));

        return (returnObject);
    }

    public static String compressStringAndReturnBase64(String srcTxt) {

        ByteArrayOutputStream rstBao = new ByteArrayOutputStream();
        GZIPOutputStream zos;
        try {
            zos = new GZIPOutputStream(rstBao);
            zos.write(srcTxt.getBytes());
            IOUtils.closeQuietly(zos);
            byte[] bytes = rstBao.toByteArray();
            String base64comp = Base64.getEncoder().encodeToString(bytes);
            System.out.println("Json String is " + srcTxt.toString().getBytes().length + " compressed " + bytes.length + " compressed Base64 " + base64comp.getBytes().length);

            return base64comp;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "";
    }

Я проверил вывод Base64, и он, кажется, работает нормально (вставил его в https://www.base64decode.org/). Кроме того, когда я проверяю с почтальоном, я получаю двоичный двоичный объект, который можно распаковать с 7-zip, если я сохранить ответ на что-то, что заканчивается на .gz.

В настройках двоичные типы носителей API Gateway установлены на / Но я бы хотел, чтобы клиент «увидел», что он был GZIP, и расшифровал его на лету. Тем не менее, когда я добавляю строку

returnObject.put("Content-Encoding", "gzip");

Я получаю {"message": "Внутренняя ошибка сервера"} и в журналах API AWS: сбой выполнения из-за ошибки конфигурации: неверный ответ Lambda прокси

Лямбда-журналы в порядке, поэтому они успешно выполнялись, просто не могли быть возвращены.

Думаю, мне нужно еще кое-что настроить на стороне шлюза API, есть идеи?

Ответы [ 2 ]

2 голосов
/ 27 апреля 2019

Похоже, что настройка бинарной поддержки на API Gateway настроена неправильно;Шлюз API пытается проанализировать ответ от вашей лямбды, а не передавать его непосредственно клиенту.

Вы можете обновить этот параметр в консоли:

API Gateway binary support

0 голосов
/ 31 мая 2019

В ваш HTTP-запрос добавьте заголовок «Accept» с типом содержимого полезной нагрузки.

Accept: application / gzip

Также в ответе HTTP должен быть заголовок «Content-Type», указывающий тип содержимого ответа.

Content-Type: application / gzip

Ваша лямбда-функция возвращает двоичные данные в кодировке Base64 в API-шлюз.Таким образом, для декодирования данных там должны быть заголовок Accept вашего HTTP-запроса и заголовки Content-type ответа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...