Skip to content

Commit 429dfa1

Browse files
Merge pull request #9819 from jmcdo29/fix/pipeline-over-pipe
fix: use pipeline over stream.pipe
2 parents 4eacd87 + 9739aa6 commit 429dfa1

File tree

5 files changed

+53
-1
lines changed

5 files changed

+53
-1
lines changed

integration/send-files/e2e/express.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,7 @@ describe('Express FileSend', () => {
6565
expect(res.text).to.be.eq(readmeString);
6666
});
6767
});
68+
it('should return an error if the file does not exist', async () => {
69+
return request(app.getHttpServer()).get('/file/not/exist').expect(400);
70+
});
6871
});

integration/send-files/src/app.controller.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ export class AppController {
3131
getFileWithHeaders(): StreamableFile {
3232
return this.appService.getFileWithHeaders();
3333
}
34+
35+
@Get('file/not/exist')
36+
getNonExistantFile(): StreamableFile {
37+
return this.appService.getFileThatDoesNotExist();
38+
}
3439
}

integration/send-files/src/app.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,8 @@ export class AppService {
3535
},
3636
);
3737
}
38+
39+
getFileThatDoesNotExist(): StreamableFile {
40+
return new StreamableFile(createReadStream('does-not-exist.txt'));
41+
}
3842
}

packages/common/file-stream/streamable-file.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,22 @@ import { types } from 'util';
33
import { isFunction } from '../utils/shared.utils';
44
import { StreamableFileOptions } from './streamable-options.interface';
55

6+
export interface StreamableHandlerResponse {
7+
statusCode: number;
8+
send: (msg: string) => void;
9+
}
10+
611
export class StreamableFile {
712
private readonly stream: Readable;
813

14+
protected handleError: (
15+
err: Error,
16+
response: StreamableHandlerResponse,
17+
) => void = (err: Error, res) => {
18+
res.statusCode = 400;
19+
res.send(err.message);
20+
};
21+
922
constructor(buffer: Uint8Array, options?: StreamableFileOptions);
1023
constructor(readable: Readable, options?: StreamableFileOptions);
1124
constructor(
@@ -38,4 +51,18 @@ export class StreamableFile {
3851
length,
3952
};
4053
}
54+
55+
get errorHandler(): (
56+
err: Error,
57+
response: StreamableHandlerResponse,
58+
) => void {
59+
return this.handleError;
60+
}
61+
62+
setErrorHandler(
63+
handler: (err: Error, response: StreamableHandlerResponse) => void,
64+
) {
65+
this.handleError = handler;
66+
return this;
67+
}
4168
}

packages/platform-express/adapters/express-adapter.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
InternalServerErrorException,
3+
Logger,
34
RawBodyRequest,
45
RequestMethod,
56
StreamableFile,
@@ -32,6 +33,7 @@ import * as cors from 'cors';
3233
import * as express from 'express';
3334
import * as http from 'http';
3435
import * as https from 'https';
36+
import { PassThrough, pipeline } from 'stream';
3537
import { ServeStaticOptions } from '../interfaces/serve-static-options.interface';
3638
import { getBodyParserOptions } from './utils/get-body-parser-options.util';
3739

@@ -46,6 +48,7 @@ type VersionedRoute = <
4648

4749
export class ExpressAdapter extends AbstractHttpAdapter {
4850
private readonly routerMethodFactory = new RouterMethodFactory();
51+
private readonly logger = new Logger(ExpressAdapter.name);
4952

5053
constructor(instance?: any) {
5154
super(instance || express());
@@ -78,7 +81,17 @@ export class ExpressAdapter extends AbstractHttpAdapter {
7881
) {
7982
response.setHeader('Content-Length', streamHeaders.length);
8083
}
81-
return body.getStream().pipe(response);
84+
return pipeline(
85+
body.getStream().once('error', (err: Error) => {
86+
body.errorHandler(err, response);
87+
}),
88+
response,
89+
(err: Error) => {
90+
if (err) {
91+
this.logger.error(err.message, err.stack);
92+
}
93+
},
94+
);
8295
}
8396
return isObject(body) ? response.json(body) : response.send(String(body));
8497
}

0 commit comments

Comments
 (0)