Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { IncomingMessage, ServerResponse } from './types/node'
import { lazyHandle, promisifyHandle } from './handle'
import type { Handle, LazyHandle, Middleware, PHandle } from './handle'
import { createError, sendError } from './error'
import { send, MIMES } from './utils'
import { send, isStream, MIMES } from './utils'

export interface Layer {
route: string
Expand Down Expand Up @@ -115,8 +115,8 @@ export function createHandle (stack: Stack, options: AppOptions): PHandle {
if (type === 'string') {
return send(res, val, MIMES.html)
} else if (type === 'object' || type === 'boolean' || type === 'number' /* IS_JSON */) {
if (val && val.buffer) {
return send(res, val)
if (val && (val.buffer || isStream(val))) {
return send(res, val, MIMES.html)
Comment thread
pi0 marked this conversation as resolved.
Outdated
} else if (val instanceof Error) {
throw createError(val)
} else {
Expand Down
13 changes: 11 additions & 2 deletions src/utils/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ export function send (res: ServerResponse, data: any, type?: string) {
}
return new Promise((resolve) => {
defer(() => {
res.end(data)
resolve(undefined)
if (isStream(data)) {
data.pipe(res)
data.on('end', () => resolve(undefined))
} else {
res.end(data)
resolve(undefined)
}
})
})
}
Expand Down Expand Up @@ -41,3 +46,7 @@ export function appendHeader (res: ServerResponse, name: string, value: string):

res.setHeader(name, current.concat(value))
}

export function isStream (data: any) {
return typeof data === 'object' && typeof data.pipe === 'function' && typeof data.on === 'function'
}
24 changes: 24 additions & 0 deletions test/app.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Readable } from 'stream'
import supertest, { SuperTest, Test } from 'supertest'
import { describe, it, expect, beforeEach } from 'vitest'
import { createApp, App } from '../src'
Expand All @@ -18,6 +19,29 @@ describe('app', () => {
expect(res.body).toEqual({ url: '/' })
})

it('can return Buffer directly', async () => {
app.use(() => Buffer.from('<h1>Hello world!</h1>', 'utf8'))
const res = await request.get('/')

expect(res.text).toBe('<h1>Hello world!</h1>')
expect(res.header['content-type']).toBe('text/html')
})

it('can return ReadableStream directly', async () => {
app.use(() => {
const readable = new Readable()
readable._read = () => {}
readable.push(Buffer.from('<h1>Hello world!</h1>', 'utf8'))
readable.push(null)
return readable
})
const res = await request.get('/')

expect(res.text).toBe('<h1>Hello world!</h1>')
expect(res.header['content-type']).toBe('text/html')
expect(res.header['transfer-encoding']).toBe('chunked')
})

it('can return HTML directly', async () => {
app.use(() => '<h1>Hello world!</h1>')
const res = await request.get('/')
Expand Down