File-based response support & static server
All checks were successful
continuous-integration/drone/push Build is passing

- Clean up UniversalPath implementation
    - Use Readable/Writable types correctly for stream methods
    - Add .list() methods for getting child files

- Make Response body specify explicit types and support
  writing Readable streams to the body

- Create a static file server that supports directory listing
This commit is contained in:
2021-07-07 20:13:23 -05:00
parent b3b5b169e8
commit f496046461
14 changed files with 893 additions and 165 deletions

View File

@@ -2,6 +2,7 @@ import {Request} from './Request'
import {ErrorWithContext, HTTPStatus, BehaviorSubject} from '../../util'
import {ServerResponse} from 'http'
import {HTTPCookieJar} from '../kernel/HTTPCookieJar'
import {Readable} from 'stream'
/**
* Error thrown when the server tries to re-send headers after they have been sent once.
@@ -47,7 +48,7 @@ export class Response {
private isBlockingWriteback = false
/** The body contents that should be written to the response. */
public body = ''
public body: string | Buffer | Uint8Array | Readable = ''
/**
* Behavior subject fired right before the response content is written.
@@ -192,18 +193,29 @@ export class Response {
* Write the headers and specified data to the client.
* @param data
*/
public async write(data: unknown): Promise<void> {
public async write(data: string | Buffer | Uint8Array | Readable): Promise<void> {
return new Promise<void>((res, rej) => {
if ( !this.sentHeaders ) {
this.sendHeaders()
}
this.serverResponse.write(data, error => {
if ( error ) {
rej(error)
} else {
res()
}
})
if ( data instanceof Readable ) {
data.pipe(this.serverResponse)
.on('finish', () => {
res()
})
.on('error', error => {
rej(error)
})
} else {
this.serverResponse.write(data, error => {
if ( error ) {
rej(error)
} else {
res()
}
})
}
})
}
@@ -212,9 +224,14 @@ export class Response {
*/
public async send(): Promise<void> {
await this.sending$.next(this)
this.setHeader('Content-Length', String(this.body?.length ?? 0))
if ( !(this.body instanceof Readable) ) {
this.setHeader('Content-Length', String(this.body?.length ?? 0))
}
await this.write(this.body ?? '')
this.end()
await this.sent$.next(this)
}