Unable to decompress using gunzip and serverless-http due to incorrect header check error, yet functions properly with a standard Node.js Express server

Currently, I am tackling an issue with the serverless framework and serverless-http library while attempting to decompress a binary request. The peculiar thing is that the exact code segment functions properly in a typical expressjs server but encounters issues when used with serverless-http.

The following portion showcases the minimal representation of a functional ordinary expressjs server:

const express = require("express");
const { unzip } = require("node:zlib");
const zlib = require("node:zlib");
const { promisify } = require("node:util");
const compression = require("compression");
const http = require("http");

const app = express();
const port = process.env.PORT || 5002;

app.use(express.json());
app.use(compression());

const do_unzip = promisify(unzip);


app.post("/unzip", async (req, res, next) => {
  const isAccepted = req.headers["content-type"] === "application/gzip";
  if (!isAccepted) return res.status(406).json({ message: "Not Acceptable" });

  const data = [];

  req.addListener("data", (chunk) => {
    data.push(Buffer.from(chunk));
  });

  req.addListener("end", async () => {
    const buff = Buffer.concat(data);

    try {
      const buffRes = await do_unzip(buff);
      const result = buffRes.toString();

      return res.status(200).json({
        result,
      });
    } catch (error) {
      next(error);
    }
  });
});



const server = http.createServer(app).listen(port, () => {
  const addressInfo = server.address();
  console.log(`Listening on port ${addressInfo.port}`);
});

Here is the minimal representation of a serverless lambda handler using serverless-http that fails to work:

const serverless = require("serverless-http");
const express = require("express");
const { gunzip } = require("node:zlib");
const zlib = require("node:zlib");
const { promisify } = require("node:util");
const compression = require("compression");

const app = express();

app.use(express.json());
app.use(compression());

const do_unzip = promisify(gunzip);

app.post("/unzip", async (req, res, next) => {
  const isAccepted = req.headers["content-type"] === "application/gzip";
  if (!isAccepted) return res.status(406).json({ message: "Not Acceptable" });

  const data = [];
  req.addListener("data", (chunk) => {
    data.push(Buffer.from(chunk));
  });
  req.addListener("end", async () => {
    const buff = Buffer.concat(data);
    try {
      const buffRes = await do_unzip(buff, {
        finishFlush: zlib.constants.Z_SYNC_FLUSH,
      });
      const result = buffRes.toString();

      return res.status(200).json({
        result,
      });
    } catch (error) {
      next(error);
    }
  });
});

app.use((err, req, res, next) => {
  console.error(err);
  return res.status(500).json({
    error: err,
    message: err.message,
  });
});


module.exports.handler = serverless(app);

When sending binary files with Postman https://i.sstatic.net/7xI7J.png,

The aforementioned code snippet encounters an error:

Error: incorrect header check
    at Zlib.zlibOnError [as onerror] (node:zlib:189:17)
    at Zlib.callbackTrampoline (node:internal/async_hooks:130:17) {
  errno: -3,
  code: 'Z_DATA_ERROR'
}

resulting in the error response:

{
    "error": {
        "errno": -3,
        "code": "Z_DATA_ERROR"
    },
    "message": "incorrect header check"
}

I am puzzled about what I might be doing incorrectly. Perhaps, should I consider employing a different approach to decompress binary files with a gz extension in the serverless expressjs application?

Answer №1

This solution is not absolutely precise, but it provides a helpful workaround.

It was effective for this handler handler.js

'use strict';
const zlib = require('zlib');

module.exports.handler = async (input, context) => {
  console.log('input', input);
  const payload = Buffer.from(input.awslogs.data, 'base64');
  zlib.gunzip(payload, function (error, result) {
    if (error) {
      console.error('an error occurred ', error);
      context.fail(error);
    } else {
      result = JSON.parse(result.toString());
      console.log('Event Data:', JSON.stringify(result, null, 2));
      context.succeed();

      return {
        statusCode: 200,
        body: JSON.stringify(
          {
            result,
          },
          null,
          2
        ),
      };
    }
  });
};

I utilized serverless invoke command test.sh

#!/bin/sh
exec serverless invoke local -f hello \
-p ./tests/2_input.json

The contents of the 2_input.json

{
  "awslogs": {
    "data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA=="
  }
}

I executed the test.sh file and received this output

$./test.sh
Running "serverless" from node_modules
input {
  awslogs: {
    data: 'H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA=='
  }
}
Event Data: {
  "messageType": "DATA_MESSAGE",
  "owner": "123456789123",
  "logGroup": "testLogGroup",
  "logStream": "testLogStream",
  "subscriptionFilters": [
    "testFilter"
  ],
  "logEvents": [
    {
      "id": "eventId1",
      "timestamp": 1440442987000,
      "message": "[ERROR] First test message"
    },
    {
      "id": "eventId2",
      "timestamp": 1440442987001,
      "message": "[ERROR] Second test message"
    }
  ]
}

I employed the AWS extension for vscode in order to obtain the 2_input.json

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transforming JSON data into comma-delimited values (with thousands separators) using Angular 5 and ES6 syntax

Is there a more elegant method to convert a JSON response into comma-separated numbers for displaying currency purposes? Here is the code I have currently: let data = { "business":{ "trasactionTableData":[ { ...

Can someone help me figure out where I'm going wrong with the JS ternary conditional operator

Looking to improve my JavaScript logic skills as a beginner. Appreciate any tips or feedback on the function and not just this specific question. I'm curious why the code outputs --> [3,5] function divisors(integer) { let divisors = [] for (le ...

JQuery drag and drop functionality experiencing issues in Chrome Browser specifically when integrated into a Joomla Article

I recently embedded a jQuery drag and drop example into my Joomla article. Surprisingly, it works perfectly fine on Firefox browser but encounters issues on Chrome. Although the drag and drop functionality works on Chrome, the problem is that the buttons b ...

Executing NPM commands in a sequential manner

If I have the following npm scripts: "scripts": { "pre-build": "echo \"Welcome\" && exit 1", "build_logic": "start cmd.exe @cmd /k \"yo esri-appbuilder-js:widget && exit 1\"", "post_build": "start C:\ ...

The state of the UI is not updating to reflect the selected item in React Native

I'm working on a component that needs to display all ingredients from my database, but I'm encountering issues with the state not updating as expected. Here are the variables: const image = require('../../assets/backgroundMeal.png'); ...

Add characterizations to object utilizing cropper plugin

After obtaining image attributes from the cropper plugin, I am looking to include two additional values: var data = $img.cropper('getData'); //Object {x: 90, y: 60, width: 720, height: 480, rotate: 0…} image_identifier = $('.image_identi ...

How can serial numbers be sorted using a JavaScript If Statement based on 2 criteria?

I'm currently enrolled in a JavaScript coding course where I am tackling a task involving validating serial numbers. The requirement is to check if a serial number is valid and then add it to an array to store all the valid serial numbers. The criteri ...

Sending data from a child component to a parent component in React

Trying to figure out how to pass the returned value of function appColor from the WeatherForecast component into a property, and then passing that property from WeatherForecast to the className of the app component. I'm new to React, so not sure how t ...

Using JavaScript to retrieve the updated timestamp of a file

Can JavaScript be used to retrieve the modified timestamp of a file? I am populating a webpage with data from a JSON file using JavaScript, and I want to display the timestamp of that file. Is there a way to do this using only JavaScript? ...

What are the potential drawbacks of relying heavily on socket.io for handling most requests versus using it primarily for pushing data to clients?

Is it advisable to switch AJAX routes (called with $.Ajax in jquery) like: GET /animals GET /animals/[id] POST /animals To socket.io events (event bound on client and server for client response): emit("animals:read") emit("animals:read", {id:asdasd}) ...

Every time I input information into the form, it keeps coming back as undefined

function displayProduct() { var product = document.getElementById("productForm"); var item = product.elements["item"].value ; document.getElementById("outputResult").innerHTML = item ; } <div> <p id="outputResult"></p> </di ...

What is the proper way to structure JSON data for communication between two Lambda functions?

I am facing an issue while sending JSON data from one parent lambda to multiple child lambdas. The data is sent as JSON from the parent lambda with double quotes, but the receiving lambda only receives it with single quotes: event: [{'account': & ...

Using ReactJS to create different behavior for checkboxes and rows in tables with Material-UI

I am looking to customize the functionality of checkboxes and table rows. Currently, clicking on a row also clicks the checkbox, and vice versa. What I would like to achieve is for clicking on a row to trigger a dialogue box, and for clicking on the chec ...

An error occurred with nextJS and the current date. The text content does not align with the server-rendered HTML, raising a warning that the content does not

When working on a component with React, NextJS and M-UI, I encountered an issue while trying to retrieve a date. The error message I received was: Unhandled Runtime Error Error: Text content does not match server-rendered HTML. Warning: Text content did n ...

The MongooseServerSelectionError has occurred due to a connection refusal at 127.0.0.1:27017. The server failed to initiate

Currently in the process of creating an API with node.js using Express.js and MongoDB. All the necessary libraries have been imported and the MongoDB connection and port have been configured. After running the npm start command, the server initiates but a ...

Nested loops with synchronous calls running in parallel

Is there a way to make synchronous calls in two nested 'for' loops in Node.JS? I have an Asynchronous call, but I am unsure how to modify it to work synchronously and go to the next iteration when create_db is done! var new_items = []; f ...

Convert Object Keys to Month Format for Sequential Display of Months in AngularJS

I'm having trouble formatting an object key to display months chronologically. I can't figure out what I'm doing wrong. Here's the code in the view: <div ng-repeat="month in months | orderBy: 'english' | date: 'MMMM&a ...

Node/Express serving static files when requested

I am a beginner in node/express and currently trying to grasp the concept of serving static files. While I have successfully served my index file, I am encountering difficulties serving other files as a response to a GET request. app.use(express.static(pa ...

Building conditionals in AngularJS expressions using if-then-else syntax

Is there a way to incorporate the ternary-operator (if-then-else construction) in an angularjs expression? For example, I have a function $scope.isExists(item) that should return a boolean value. I would like to do something like this: <div ng-repeater ...

A guide to setting a custom icon for the DatePicker component in Material-UI 5

Seeking to incorporate custom Icons from react-feathers, I have implemented a CustomIcon component which returns the desired icon based on the name prop. Below is the code for this component. import React from 'react'; import * as Icon from &apo ...