CodeGenieApp / CodeGenieApp/serverless-express

Getting "stream is not readable" since 4.16.0

Offen
#693 2 Kommentare 12 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
JavaScript
Sterne
5.3k
Forks
676
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

The #692 PR introduced a bug when using with express and an async middleware: the IncomingMessage/Request (stream) is marked as not readable and fails when used with body-parser (for example).

Affected version: 4.16.0
Express version: 4 (didn't test it on 5)
Body parser version: 1.20.3

For the code attached, running with 4.15.0 yields:
```
{
statusCode: 200,
body: 'Hello World!',
isBase64Encoded: false,
headers: {
'x-powered-by': 'Express',
'content-type': 'text/html; charset=utf-8',
'content-length': '12',
etag: 'W/"c-Lve95gjOVATpfV8EL5X4nxwjKHE"'
}
}
```

Running with 4.16.0 yields:

```
{
statusCode: 500,
body: '\n' +
'\n' +
'\n' +
'\n' +
'Error\n' +
'\n' +
'\n' +
'

InternalServerError: stream is not readable
   at readStream (node_modules/raw-body/index.js:185:17)
   at getRawBody ... (same as below)' +
'\n' +
'\n',
isBase64Encoded: false,
headers: {
'x-powered-by': 'Express',
'content-security-policy': "default-src 'none'",
'x-content-type-options': 'nosniff',
'content-type': 'text/html; charset=utf-8',
'content-length': 1262
}
}
InternalServerError: stream is not readable
at readStream (node_modules/raw-body/index.js:185:17)
at getRawBody (node_modules/raw-body/index.js:116:12)
at read (node_modules/body-parser/lib/read.js:79:3)
at jsonParser (node_modules/body-parser/lib/types/json.js:138:5)
at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (node_modules/express/lib/router/index.js:328:13)
at node_modules/express/lib/router/index.js:286:9
at Function.process_params (node_modules/express/lib/router/index.js:346:12)
at next (node_modules/express/lib/router/index.js:280:10)
at src/example.ts:10:3
```

Code to reproduce:
```typescript
import serverlessExpress from '@codegenie/serverless-express';
import express from 'express';
import bodyParser from 'body-parser';
import { promisify } from 'node:util';

const app = express();

app.use(async (req, res, next) => {
// Remove this line to "remove the problem"
await promisify(setTimeout)(1000);
next();
});

app.use(bodyParser.json());

app.use((req, res) => {
res.send('Hello World!');
});

const serverlessExpressInstance = serverlessExpress({ app });

export async function handler(event: any, context: any, callback: any) {
return serverlessExpressInstance(event, context, callback);
}

handler(
{
version: '2.0',
rawPath: '/path/to/resource',
headers: {
"Content-Type": "application/json",
"Content-Length": "2",
},
requestContext: {
http: {
method: 'POST',
path: '/path/to/resource',
protocol: 'HTTP/1.1',
sourceIp: '192.168.0.1/32',
userAgent: 'agent',
},
},
body: "{}",
isBase64Encoded: false,
},
{} as any,
() => {},
)
.then(console.log.bind(console))
.catch(console.error.bind(console));
```

I believe [this](https://github.com/CodeGenieApp/serverless-express/blob/5944638c128e82ea41915fc724e72cb8b3189bbd/src/transport.js#L163) is the culprit. Express doesn't return a promise from the handle function, so if there's a middleware that starts an async operation the function will return and the stream will be marked as not readable.

```typescript
await framework.sendRequest({ app, request, response })
markHttpRequestAsCompleted(request) // <-- maybe this should be moved down to after the the stream completes?
await waitForStreamComplete(response)
```

Small note, initially I had trouble finding this because I thought we were actually using vendia's serverless-express version. After fiddling with it for a couple of hours I realized it was actually "exporting" codegenie's version. So leaving this note here, in case someone else thinks they're using vendia's.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Start at src/transport.js around the linked line 163 and reproduce the failure with the supplied TypeScript example using async middleware and body-parser. Trace when the request stream is marked complete relative to Express middleware and response completion, then verify that the example succeeds with the affected version and its regression is covered by a test.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
aws, express, javascript, node.js, typescript
Bereich
api, backend, cloud
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
45/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.