Skip to content

Commit 6740bfa

Browse files
committed
refactor(response): stream file error callback can return body and status code
1 parent 0a84014 commit 6740bfa

File tree

4 files changed

+32
-19
lines changed

4 files changed

+32
-19
lines changed

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"del-cli": "^3.0.0",
4848
"doctoc": "^1.4.0",
4949
"eslint": "^6.8.0",
50-
"eslint-plugin-adonis": "^1.0.7",
50+
"eslint-plugin-adonis": "^1.0.8",
5151
"fastify": "^2.12.0",
5252
"http-status-codes": "^1.4.0",
5353
"husky": "^4.2.3",

src/Response/index.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,10 @@ export class Response extends Macroable implements ResponseContract {
262262
/**
263263
* Stream the body to the response and handles cleaning up the stream
264264
*/
265-
private streamBody (body: ResponseStream, errorCallback?: ((error: NodeJS.ErrnoException) => any)) {
265+
private streamBody (
266+
body: ResponseStream,
267+
errorCallback?: ((error: NodeJS.ErrnoException) => [string, number?]),
268+
) {
266269
return new Promise((resolve) => {
267270
let finished = false
268271

@@ -280,7 +283,7 @@ export class Response extends Macroable implements ResponseContract {
280283
destroy(body)
281284

282285
if (typeof (errorCallback) === 'function') {
283-
this.endResponse(errorCallback(error))
286+
this.endResponse(...errorCallback(error))
284287
} else {
285288
this.endResponse(
286289
error.code === 'ENOENT' ? 'File not found' : 'Cannot process file',
@@ -317,7 +320,7 @@ export class Response extends Macroable implements ResponseContract {
317320
private async streamFileForDownload (
318321
filePath: string,
319322
generateEtag: boolean,
320-
errorCallback?: ((error: NodeJS.ErrnoException) => any),
323+
errorCallback?: ((error: NodeJS.ErrnoException) => [string, number?]),
321324
) {
322325
try {
323326
const stats = await statFn(filePath)
@@ -374,9 +377,12 @@ export class Response extends Macroable implements ResponseContract {
374377
return this.streamBody(createReadStream(filePath), errorCallback)
375378
} catch (error) {
376379
if (typeof (errorCallback) === 'function') {
377-
this.endResponse(errorCallback(error))
380+
this.endResponse(...errorCallback(error))
378381
} else {
379-
this.endResponse('Cannot process file', 404)
382+
this.endResponse(
383+
error.code === 'ENOENT' ? 'File not found' : 'Cannot process file',
384+
error.code === 'ENOENT' ? 404 : 500,
385+
)
380386
}
381387
}
382388
}
@@ -726,7 +732,10 @@ export class Response extends Macroable implements ResponseContract {
726732
* }
727733
* ```
728734
*/
729-
public stream (body: ResponseStream, errorCallback?: ((error: NodeJS.ErrnoException) => any)): void {
735+
public stream (
736+
body: ResponseStream,
737+
errorCallback?: ((error: NodeJS.ErrnoException) => [string, number?]),
738+
): void {
730739
if (typeof (body.pipe) !== 'function' || !body.readable || typeof (body.read) !== 'function') {
731740
throw new Error('response.stream accepts a readable stream only')
732741
}
@@ -765,7 +774,7 @@ export class Response extends Macroable implements ResponseContract {
765774
public download (
766775
filePath: string,
767776
generateEtag: boolean = this.config.etag,
768-
errorCallback?: ((error: NodeJS.ErrnoException) => any),
777+
errorCallback?: ((error: NodeJS.ErrnoException) => [string, number?]),
769778
): void {
770779
this.lazyBody = {
771780
writer: this.streamFileForDownload,
@@ -784,7 +793,7 @@ export class Response extends Macroable implements ResponseContract {
784793
name?: string,
785794
disposition?: string,
786795
generateEtag?: boolean,
787-
errorCallback?: ((error: NodeJS.ErrnoException) => any),
796+
errorCallback?: ((error: NodeJS.ErrnoException) => [string, number?]),
788797
) {
789798
name = name || filePath
790799
this.header('Content-Disposition', contentDisposition(name, { type: disposition }))

test/response.spec.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ test.group('Response', (group) => {
475475
readStream.emit('error', new Error('Missing file'))
476476
}
477477

478-
response.stream(readStream, ({ message }) => message)
478+
response.stream(readStream, ({ message }) => [message])
479479
response.finish()
480480
})
481481

@@ -526,14 +526,16 @@ test.group('Response', (group) => {
526526
})
527527

528528
test('write errors as response when downloading folder', async (assert) => {
529+
await fs.ensureRoot()
530+
529531
const server = createServer((req, res) => {
530532
const config = fakeConfig()
531533
const response = new Response(req, res, config)
532534
response.download(join(fs.basePath))
533535
response.finish()
534536
})
535537

536-
const { text } = await supertest(server).get('/').expect(404)
538+
const { text } = await supertest(server).get('/').expect(500)
537539
assert.equal(text, 'Cannot process file')
538540
})
539541

@@ -546,20 +548,22 @@ test.group('Response', (group) => {
546548
})
547549

548550
const { text } = await supertest(server).get('/').expect(404)
549-
assert.equal(text, 'Cannot process file')
551+
assert.equal(text, 'File not found')
550552
})
551553

552-
test('raise errors as response when file is missing', async (assert) => {
554+
test('return custom message and status when file is missing', async (assert) => {
553555
const server = createServer(async (req, res) => {
554556
const config = fakeConfig()
555557
const response = new Response(req, res, config)
556558

557-
response.download(join(fs.basePath, 'hello.html'), false)
559+
response.download(join(fs.basePath, 'hello.html'), false, () => {
560+
return ['Missing file', 400]
561+
})
558562
response.finish()
559563
})
560564

561-
const { text } = await supertest(server).get('/').expect(404)
562-
assert.equal(text, 'Cannot process file')
565+
const { text } = await supertest(server).get('/').expect(400)
566+
assert.equal(text, 'Missing file')
563567
})
564568

565569
test('do not stream file on HEAD calls', async (assert) => {

0 commit comments

Comments
 (0)