CodeGenieApp / CodeGenieApp/serverless-express
Getting "stream is not readable" since 4.16.0
- 主要言語
- JavaScript
- スター
- 5.3k
- フォーク
- 676
- PR マージ指標
- 30日以内にマージされた PR はありません
説明
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.
コントリビューションガイド
調査の方向性
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.
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- aws, express, javascript, node.js, typescript
- 領域
- api, backend, cloud
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 45/100