diff --git a/benchmark/regexp_cve.mjs b/benchmark/regexp_cve.mjs new file mode 100644 index 0000000..6ca50fb --- /dev/null +++ b/benchmark/regexp_cve.mjs @@ -0,0 +1,19 @@ +import { printTime } from './utils.mjs' + +var arg = ""; +for (var i = 0; i < 1000000; i++) { + arg += "\\"; +} +arg += "◎"; + +let s1 = process.hrtime.bigint() +let s2 = process.hrtime.bigint() + +arg = arg.replace(/(?=\\*?)"/g, '$1$1\\"'); +arg = arg.replace(/(?=\\*?)$/, '$1$1'); + +let s3 = process.hrtime.bigint() + +let time = s3 - s2 - (s2 - s1) + +printTime(time) diff --git a/benchmark/router_v2_compile.mjs b/benchmark/router_v2_compile.mjs index 1533eec..cf93c4c 100644 --- a/benchmark/router_v2_compile.mjs +++ b/benchmark/router_v2_compile.mjs @@ -1,13 +1,16 @@ -import { compilePaths } from "../router_v2.mjs" +import { FlaskaRouter } from "../flaska.mjs" import { printTime } from './utils.mjs' import * as consts from './const.js' let paths = consts.allManyRoutes.map(x => ({ path: x })) +let router = new FlaskaRouter() +router.paths = paths + let s1 = process.hrtime.bigint() let s2 = process.hrtime.bigint() -compilePaths(paths) +router.compile() let s3 = process.hrtime.bigint() diff --git a/benchmark/utils.mjs b/benchmark/utils.mjs index d26a56b..d4a448e 100644 --- a/benchmark/utils.mjs +++ b/benchmark/utils.mjs @@ -1,6 +1,6 @@ export function printTime (t) { let time = Number(t) - let units = ['n', 'μ', 'm', 'c', 's'] + let units = ['n', 'μ', 'ms', 's'] let unit = units[0] let unitPower = 1 for (let i = 0; i < units.length; i++) { @@ -9,7 +9,7 @@ export function printTime (t) { break } unitPower = power - unit = units[i] + unit = units[i + 1] } console.log(t, '=', Number((time / unitPower).toFixed(2)), unit) -} \ No newline at end of file +} diff --git a/flaska.d.ts b/flaska.d.ts new file mode 100644 index 0000000..bea95aa --- /dev/null +++ b/flaska.d.ts @@ -0,0 +1,147 @@ +import { IncomingMessage, ServerResponse, Server } from 'node:http' +import { Stats } from 'node:fs' + +type Maybe = T | null | undefined + +export const MimeTypeDb: Record> + +export type Logger = { + fatal: (...data: any[]) => void, + error: (...data: any[]) => void, + warn: (...data: any[]) => void, + info: (...data: any[]) => void, + debug: (...data: any[]) => void, + trace: (...data: any[]) => void, + log: (...data: any[]) => void, +} + +export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH' | 'HEAD' + +export type Context = { + log: Logger, + req: IncomingMessage, + res: ServerResponse>, + method: Method, + url: string, + search: string, + state: Record, + status: number, + query: URLSearchParams, + body: any, + type: string | null, + length: number | null, + headers: Record, + aborted?: boolean, +} + +export interface BodyHasHandler = { handleRequest: (ctx: Context) => any } +export type HandlerSync = (ctx: Context) => void +export type HandlerAsync = (ctx: Context) => Promise +export type Handler = HandlerSync | HandlerAsync + +export function QueryHandler(): Handler +export function JsonHandler(options: { sizeLimit?: number | null } = {}): Handler +export function CorsHandler(options: { + allowedMethod?: Maybe, + allowedOrigins?: Maybe, + allowedHeaders?: Maybe, + credentials?: Maybe, + exposeHeaders?: Maybe, + maxAge?: Maybe, +} = {}): Handler + +export type File = { name: string, path: string, filename: string } + +export class HttpError { + constructor(statusCode: number, message: string, body: any) + status: number + body: any +} + +export class FileResponse implements BodyHasHandler { + constructor(filepath: string, stat: Stats) + filepath: string + stat: Stats + handleRequst(ctx: Context): any +} + +export function FormidableHandler(formidable: any, options: { + parseFields?: Maybe, + uploadDir?: Maybe, + filename?: Maybe<(file: File) => string>, + maxFileSize?: Maybe, + maxFieldSize?: Maybe, + maxFields?: Maybe, + rename?: Maybe, +} = {}): Handler + +export class RouterError { + constructor(route1: any, route2: any, message: string) + routeA: any + routeB: any +} + +export type FlaskaRouterMatch = { + path: { + path: string, + handlers: Handler[], + }, + params: Record, +} + +export class FlaskaRouter { + constructor() + addRoute(path: string, handler: Handler): void + addRoute(path: string, middlewares: Handler | Handler[], handler: Handler): void + compile(): void + match(url: string): FlaskaRouterMatch | null +} + +export type FlaskaOptions = { + defaultHeaders?: Maybe>, + log?: Maybe, + nonce?: Maybe>, + nonceCacheLength: Maybe, + appendHeaders?: Maybe>, +} + +export class Flaska { + log: Logger + server: Server + routers: { + GET: FlaskaRouter, + POST: FlaskaRouter, + PUT: FlaskaRouter, + DELETE: FlaskaRouter, + OPTIONS: FlaskaRouter, + PATCH: FlaskaRouter, + HEAD: FlaskaRouter, + } + get: FlaskaRouter['addRoute'] + post: FlaskaRouter['addRoute'] + put: FlaskaRouter['addRoute'] + delete: FlaskaRouter['addRoute'] + options: FlaskaRouter['addRoute'] + patch: FlaskaRouter['addRoute'] + head: FlaskaRouter['addRoute'] + + constructor(options: FlaskaOptions) + devMode(): void + on404(handler: Handler): void + onerror(handler: Handler): void + onreqerror(handler: Handler): void + onreserror(handler: Handler): void + before(handler: HandlerSync): void + beforeAsync(handler: HandlerAsync): void + after(handler: HandlerSync): void + afterAsync(handler: HandlerAsync): void + listen(port: number): void + listen(port: number, ip: string): void + listen(port: number, cb: () => void): void + listen(port: number, ip:string, cb: () => void): void + listenAsync(port: number): Promise + listenAsync(port: number, ip: string): Promise + listenAsync(port: number, cb: () => void): Promise + listenAsync(port: number, ip:string, cb: () => void): Promise + closeAsync(): Promise +} diff --git a/flaska.mjs b/flaska.mjs index ce92c36..e949c6c 100644 --- a/flaska.mjs +++ b/flaska.mjs @@ -37,10 +37,6 @@ export const MimeTypeDb = getDb() * Router */ -export const ErrorCodes = { - ERR_CONNECTION_ABORTED: 'ERR_CON_ABORTED' -} - // Taken from https://github.com/nfp-projects/koa-lite/blob/master/lib/statuses.js const statuses = { 100: 'Continue', 101: 'Switching Protocols', 102: 'Processing', 103: 'Early Hints', @@ -935,7 +931,7 @@ ctx.state.nonce = nonce; this._afterAsync.push(handler) } - requestStart(req, res) { + __requestStart(req, res) { let url = req.url let search = '' let hasSearch = url.indexOf('?') @@ -965,14 +961,14 @@ ctx.state.nonce = nonce; ctx.aborted = true } this._onreqerror(err, ctx) - this.requestEnded(ctx) + this.__requestEnded(ctx) }) res.on('error', (err) => { this._onreserror(err, ctx) }) res.on('finish', () => { - this.requestEnded(ctx) + this.__requestEnded(ctx) }) try { @@ -980,59 +976,59 @@ ctx.state.nonce = nonce; if (this._beforeAsyncCompiled) { return this._beforeAsyncCompiled(ctx) .then(() => { - this.requestStartInternal(ctx) + this.__requestStartInternal(ctx) }).catch(err => { - this.requestEnd(err, ctx) + this.__requestEnd(err, ctx) }) } - this.requestStartInternal(ctx) + this.__requestStartInternal(ctx) } catch (err) { - this.requestEnd(err, ctx) + this.__requestEnd(err, ctx) } } - requestStartInternal(ctx) { + __requestStartInternal(ctx) { let route = this.routers[ctx.method].match(ctx.url) if (!route) { let middle = this._on404(ctx) if (middle && middle.then) { return middle.then(() => { - this.requestEnd(null, ctx) + this.__requestEnd(null, ctx) }, err => { - this.requestEnd(err, ctx) + this.__requestEnd(err, ctx) }) } - return this.requestEnd(null, ctx) + return this.__requestEnd(null, ctx) } ctx.params = route.params - let handlers = this.runHandlers(ctx, route.path.handlers, 0) + let handlers = this.__runHandlers(ctx, route.path.handlers, 0) if (handlers && handlers.then) { return handlers.then(() => { - this.requestEnd(null, ctx) + this.__requestEnd(null, ctx) }, err => { - this.requestEnd(err, ctx) + this.__requestEnd(err, ctx) }) } - this.requestEnd(null, ctx) + this.__requestEnd(null, ctx) } - runHandlers(ctx, middles, index) { + __runHandlers(ctx, middles, index) { for (let i = index; i < middles.length; i++) { let res = middles[i](ctx) if (res && res.then) { return res.then(() => { - return this.runHandlers(ctx, middles, i + 1) + return this.__runHandlers(ctx, middles, i + 1) }) } } } - requestEnd(orgErr, ctx) { + __requestEnd(orgErr, ctx) { let err = orgErr let handleUsed = Boolean(ctx.body && ctx.body.handleRequest) if (handleUsed) { @@ -1120,7 +1116,7 @@ ctx.state.nonce = nonce; } } - requestEnded(ctx) { + __requestEnded(ctx) { if (ctx.finished) return ctx.finished = true @@ -1134,7 +1130,7 @@ ctx.state.nonce = nonce; } } - compile() { + __compile() { let types = ['before', 'after'] for (let i = 0; i < types.length; i++) { let type = types[i] @@ -1170,9 +1166,9 @@ ctx.state.nonce = nonce; this.routers.PATCH.compile() } - create() { - this.compile() - this.server = this.http.createServer(this.requestStart.bind(this)) + __create() { + this.__compile() + this.server = this.http.createServer(this.__requestStart.bind(this)) this.server.on('connection', function (socket) { // Set socket idle timeout in milliseconds @@ -1197,7 +1193,7 @@ ctx.state.nonce = nonce; throw new Error('Flaska.listen() called with non-number in port') } - this.create() + this.__create() this.server.listen(port, ip, cb) } @@ -1207,7 +1203,7 @@ ctx.state.nonce = nonce; return Promise.reject(new Error('Flaska.listen() called with non-number in port')) } - this.create() + this.__create() if (this.server.listenAsync && typeof(this.server.listenAsync) === 'function') { return this.server.listenAsync(port, ip) diff --git a/package.json b/package.json index 8aad104..5626430 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "flaska", - "version": "1.4.0", + "version": "1.5.0", "description": "Flaska is a micro web-framework for node. It is designed to be fast, simple and lightweight, and is distributed as a single file module with no dependencies.", "main": "flaska.mjs", "scripts": { "test": "eltro -r dot", "test:watch": "eltro -r dot -w test" }, + "types": "flaska.d.ts", "watch": { "test": { "patterns": [ diff --git a/test/flaska.api.test.mjs b/test/flaska.api.test.mjs index 9485ee5..9c49fd7 100644 --- a/test/flaska.api.test.mjs +++ b/test/flaska.api.test.mjs @@ -668,7 +668,7 @@ t.describe('#compile()', function() { flaska.before(function(ctx) { ctx.c = 3 }) flaska.before(function(ctx) { ctx.d = 4 }) assert.notOk(flaska._beforeCompiled) - flaska.compile() + flaska.__compile() assert.ok(flaska._beforeCompiled) assert.notOk(flaska._beforeAsyncCompiled) assert.strictEqual(typeof(flaska._beforeCompiled), 'function') @@ -686,7 +686,7 @@ t.describe('#compile()', function() { flaska.beforeAsync(function(ctx) { return new Promise(function(res) { ctx.c = 3; res() }) }) flaska.beforeAsync(function(ctx) { ctx.d = 4 }) assert.notOk(flaska._beforeAsyncCompiled) - flaska.compile() + flaska.__compile() assert.ok(flaska._beforeAsyncCompiled) assert.strictEqual(typeof(flaska._beforeAsyncCompiled), 'function') let ctx = createCtx() @@ -704,7 +704,7 @@ t.describe('#compile()', function() { flaska.after(function(ctx) { ctx.c = 3 }) flaska.after(function(ctx) { ctx.d = 4 }) assert.notOk(flaska._afterCompiled) - flaska.compile() + flaska.__compile() assert.ok(flaska._afterCompiled) assert.notOk(flaska._afterAsyncCompiled) assert.strictEqual(typeof(flaska._afterCompiled), 'function') @@ -722,7 +722,7 @@ t.describe('#compile()', function() { flaska.afterAsync(function(ctx) { return new Promise(function(res) { ctx.c = 3; res() }) }) flaska.afterAsync(function(ctx) { ctx.d = 4 }) assert.notOk(flaska._afterAsyncCompiled) - flaska.compile() + flaska.__compile() assert.ok(flaska._afterAsyncCompiled) assert.strictEqual(typeof(flaska._afterAsyncCompiled), 'function') let ctx = createCtx() @@ -738,13 +738,13 @@ t.describe('#compile()', function() { t.describe('#runHandlers()', function() { t.test('should work with empty array', function() { let flaska = new Flaska({}, faker) - flaska.runHandlers({}, [], 0) + flaska.__runHandlers({}, [], 0) }) t.test('should work with correct index', function() { let checkIsTrue = false let flaska = new Flaska({}, faker) - flaska.runHandlers({}, [ + flaska.__runHandlers({}, [ function() { throw new Error('should not be thrown') }, function() { throw new Error('should not be thrown') }, function() { throw new Error('should not be thrown') }, @@ -757,7 +757,7 @@ t.describe('#runHandlers()', function() { const assertCtx = createCtx({ a: 1 }) let checkCounter = 0 let flaska = new Flaska({}, faker) - flaska.runHandlers(assertCtx, [ + flaska.__runHandlers(assertCtx, [ function(ctx) { assert.strictEqual(ctx, assertCtx); checkCounter++ }, function(ctx) { assert.strictEqual(ctx, assertCtx); checkCounter++ }, function(ctx) { assert.strictEqual(ctx, assertCtx); checkCounter++ }, @@ -771,7 +771,7 @@ t.describe('#runHandlers()', function() { const assertCtx = createCtx({ a: 1 }) let checkCounter = 0 let flaska = new Flaska({}, faker) - let result = flaska.runHandlers(assertCtx, [ + let result = flaska.__runHandlers(assertCtx, [ function(ctx) { assert.strictEqual(ctx, assertCtx); assert.strictEqual(checkCounter, 0); checkCounter++ }, function(ctx) { assert.strictEqual(ctx, assertCtx); assert.strictEqual(checkCounter, 1); checkCounter++ }, function(ctx) { return new Promise(function(res) { assert.strictEqual(ctx, assertCtx); assert.strictEqual(checkCounter, 2); checkCounter++; res() }) }, @@ -793,19 +793,19 @@ t.describe('#runHandlers()', function() { const assertError = { a: 1 } let checkCounter = 0 let flaska = new Flaska({}, faker) - let err = await assert.isRejected(flaska.runHandlers({}, [ + let err = await assert.isRejected(flaska.__runHandlers({}, [ function() { }, function() { return new Promise(function(res, rej) { rej(assertError) }) }, function() { throw new Error('should not be seen') }, ], 0)) assert.strictEqual(err, assertError) - err = await assert.isRejected(flaska.runHandlers({}, [ + err = await assert.isRejected(flaska.__runHandlers({}, [ function() { }, function() { return Promise.reject(assertError) }, function() { throw new Error('should not be seen') }, ], 0)) assert.strictEqual(err, assertError) - err = await assert.isRejected(flaska.runHandlers({}, [ + err = await assert.isRejected(flaska.__runHandlers({}, [ function() { }, function() { return Promise.resolve() }, function() { throw assertError }, @@ -828,7 +828,7 @@ t.describe('#listen()', function() { t.test('it should automatically call compile', function() { let assertCalled = false let flaska = new Flaska({}, faker) - flaska.compile = function() { assertCalled = true } + flaska.__compile = function() { assertCalled = true } flaska.listen(404) assert.strictEqual(assertCalled, true) }) @@ -847,8 +847,8 @@ t.describe('#listen()', function() { checkListenCb = cb }) let flaska = new Flaska({}, testFaker) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } @@ -871,8 +871,8 @@ t.describe('#listen()', function() { checkListenCb = cb }) let flaska = new Flaska({}, testFaker) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } @@ -891,14 +891,14 @@ t.describe('#listen()', function() { checkHandler = cb }) let flaska = new Flaska({}, testFaker) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } flaska.listen(404) assert.strictEqual(typeof(checkHandler), 'function') - assert.notStrictEqual(checkHandler, flaska.requestStart) + assert.notStrictEqual(checkHandler, flaska.__requestStart) assert.notStrictEqual(checkIsTrue, true) assert.notStrictEqual(checkInternalThis, flaska) checkHandler() @@ -929,7 +929,7 @@ t.describe('#listenAsync()', function() { t.test('it should automatically call compile', async function() { let assertCalled = false let flaska = new Flaska({}, faker) - flaska.compile = function() { assertCalled = true } + flaska.__compile = function() { assertCalled = true } await flaska.listenAsync(404) assert.strictEqual(assertCalled, true) }) @@ -947,8 +947,8 @@ t.describe('#listenAsync()', function() { }) let flaska = new Flaska({}, testFaker) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } @@ -968,8 +968,8 @@ t.describe('#listenAsync()', function() { cb() }) let flaska = new Flaska({}, testFaker) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } @@ -992,8 +992,8 @@ t.describe('#listenAsync()', function() { } } }) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } @@ -1016,8 +1016,8 @@ t.describe('#listenAsync()', function() { } } }) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } @@ -1036,14 +1036,14 @@ t.describe('#listenAsync()', function() { checkHandler = cb }) let flaska = new Flaska({}, testFaker) - assert.ok(flaska.requestStart) - flaska.requestStart = function() { + assert.ok(flaska.__requestStart) + flaska.__requestStart = function() { checkInternalThis = this checkIsTrue = true } await flaska.listenAsync(404) assert.strictEqual(typeof(checkHandler), 'function') - assert.notStrictEqual(checkHandler, flaska.requestStart) + assert.notStrictEqual(checkHandler, flaska.__requestStart) assert.notStrictEqual(checkIsTrue, true) assert.notStrictEqual(checkInternalThis, flaska) checkHandler() diff --git a/test/flaska.in.test.mjs b/test/flaska.in.test.mjs index 6cbc66b..0512fc4 100644 --- a/test/flaska.in.test.mjs +++ b/test/flaska.in.test.mjs @@ -17,9 +17,9 @@ t.describe('#requestStart()', function() { flaska.onreqerror(onReqError) flaska.onreserror(onResError) - flaska.requestEnded = onEnded + flaska.__requestEnded = onEnded - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(assertReq.on.callCount, 1) assert.strictEqual(assertRes.on.callCount, 2) @@ -49,7 +49,7 @@ t.describe('#requestStart()', function() { throw new Error() } - flaska.requestStart(assertReq, assertRes) + flaska.__requestStart(assertReq, assertRes) }) t.test('calls beforeCompiled correctly', function(cb) { @@ -58,7 +58,7 @@ t.describe('#requestStart()', function() { const assertRes = createRes({ b: 2 }) let flaska = new Flaska({}, faker) - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) assert.deepStrictEqual(ctx.state, {}) @@ -71,7 +71,7 @@ t.describe('#requestStart()', function() { throw assertError } - flaska.requestStart(assertReq, assertRes) + flaska.__requestStart(assertReq, assertRes) }) t.test('calls beforeAsyncCompiled correctly if defined', function(cb) { @@ -79,7 +79,7 @@ t.describe('#requestStart()', function() { const assertReq = createReq({ url: '', a: 1 }) const assertRes = createRes({ b: 2 }) let flaska = new Flaska({}, faker) - flaska.compile() + flaska.__compile() flaska._beforeAsyncCompiled = function(ctx) { assert.strictEqual(ctx.req, assertReq) @@ -87,7 +87,7 @@ t.describe('#requestStart()', function() { return Promise.resolve().then(function() { return Promise.reject(assertError) }) } - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) assert.deepStrictEqual(ctx.state, {}) @@ -95,7 +95,7 @@ t.describe('#requestStart()', function() { assert.strictEqual(ctx.res, assertRes) }) - flaska.requestStart(assertReq, assertRes) + flaska.__requestStart(assertReq, assertRes) }) t.test('calls correct router with correct url and context', function(cb) { @@ -106,7 +106,7 @@ t.describe('#requestStart()', function() { const assertLog = { info: function() {}, error: function() {} } let flaska = new Flaska({ log: assertLog }, faker) assert.strictEqual(flaska.log, assertLog) - flaska.compile() + flaska.__compile() flaska.routers.test = { match: function(path) { @@ -115,7 +115,7 @@ t.describe('#requestStart()', function() { } } - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) @@ -145,7 +145,7 @@ t.describe('#requestStart()', function() { assert.ok(new Date(ctx.headers['Date']).getDate()) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: assertPath + assertSearch, method: assertMethod, }), createRes()) @@ -160,7 +160,7 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({ defaultHeaders: defaultHeaders, }, faker) - flaska.compile() + flaska.__compile() flaska.routers.test = { match: function(path) { @@ -168,7 +168,7 @@ t.describe('#requestStart()', function() { } } - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) let keys = Object.keys(defaultHeaders) @@ -179,7 +179,7 @@ t.describe('#requestStart()', function() { assert.ok(ctx.headers['Date']) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/', method: 'test', }), createRes()) @@ -192,7 +192,7 @@ t.describe('#requestStart()', function() { const assertSearch = '?asdf=test' let calledBefore = false let flaska = new Flaska({}, faker) - flaska.compile() + flaska.__compile() flaska._beforeAsyncCompiled = function() { calledBefore = true return Promise.resolve() @@ -205,7 +205,7 @@ t.describe('#requestStart()', function() { } } - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(calledBefore) assert.strictEqual(err, assertError) @@ -214,7 +214,7 @@ t.describe('#requestStart()', function() { assert.strictEqual(ctx.method, assertMethod) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: assertPath + assertSearch, method: assertMethod, }), createRes()) @@ -227,7 +227,7 @@ t.describe('#requestStart()', function() { let checkMiddleCtx = null let flaska = new Flaska({}, faker) - flaska.compile() + flaska.__compile() flaska.routers.GET.match = function() { return { @@ -235,14 +235,14 @@ t.describe('#requestStart()', function() { params: assertParams, } } - flaska.runHandlers = function(ctx, middles, index) { + flaska.__runHandlers = function(ctx, middles, index) { assert.strictEqual(index, 0) assert.strictEqual(middles, assertMiddles) checkMiddleCtx = ctx throw assertError } - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) @@ -250,7 +250,7 @@ t.describe('#requestStart()', function() { assert.strictEqual(ctx.params, assertParams) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '', method: 'GET', }), createRes({})) @@ -267,16 +267,16 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.get('/:id', handler) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) @@ -292,16 +292,16 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.on404(on404Error) flaska.get('/test', function() { throw new Error('should not be called') }) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(on404Error.callCount, 1) assert.strictEqual(on404Error.firstCall[0], ctx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/nope', method: 'GET', }), createRes()) @@ -318,15 +318,15 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.on404(on404Error) flaska.get('/test', function() { throw new Error('should not be called') }) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.strictEqual(err, assertError) assert.ok(ctx) assert.strictEqual(ctx, checkCtx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/nope', method: 'GET', }), createRes()) @@ -342,15 +342,15 @@ t.describe('#requestStart()', function() { throw assertError }) flaska.get('/test', function() { throw new Error('should not be called') }) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.strictEqual(err, assertError) assert.ok(ctx) assert.strictEqual(ctx, checkCtx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/nope', method: 'GET', }), createRes()) @@ -366,15 +366,15 @@ t.describe('#requestStart()', function() { throw assertError }] flaska.get('/test', middles, function() { throw new Error('should not be called') }) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.strictEqual(err, assertError) assert.ok(ctx) assert.strictEqual(ctx, checkCtx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) @@ -389,15 +389,15 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.get('/::path', handler) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(ctx.body, assertBody) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test/something/here', method: 'GET', }), createRes()) @@ -408,7 +408,7 @@ t.describe('#requestStart()', function() { const assertMiddles = [1] let flaska = new Flaska({}, faker) - flaska.compile() + flaska.__compile() flaska.routers.GET.match = function() { return { @@ -416,17 +416,17 @@ t.describe('#requestStart()', function() { middlewares: assertMiddles, } } - flaska.runHandlers = function() { + flaska.__runHandlers = function() { return Promise.resolve().then(function() { return Promise.reject(assertError) }) } - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '', method: 'GET', }), createRes()) @@ -443,16 +443,16 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.get('/:id', [function() { return Promise.resolve() }], handler) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) @@ -469,16 +469,16 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.get('/:id', [function() { return Promise.resolve() }], handler) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) @@ -503,16 +503,16 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.get('/::path', [middle], handler) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(ctx.body, assertBody) assert.strictEqual(ctx.state, assertState) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test/something/here', method: 'GET', }), createRes()) @@ -531,16 +531,16 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.get('/:id', handler) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) @@ -557,15 +557,15 @@ t.describe('#requestStart()', function() { let flaska = new Flaska({}, faker) flaska.get('/::path', [], handler) - flaska.compile() + flaska.__compile() - flaska.requestEnd = cb.finish(function(err, ctx) { + flaska.__requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(ctx.body, assertBody) }) - flaska.requestStart(createReq({ + flaska.__requestStart(createReq({ url: '/test/something/here', method: 'GET', }), createRes()) diff --git a/test/flaska.out.test.mjs b/test/flaska.out.test.mjs index d793b04..40fb9c1 100644 --- a/test/flaska.out.test.mjs +++ b/test/flaska.out.test.mjs @@ -33,9 +33,9 @@ t.describe('#requestEnd()', function() { inctx.body = assertBody }) - flaska.requestEnd(assertError, ctx) + flaska.__requestEnd(assertError, ctx) }) - + t.test('calls backup onerror correctly if error throws', function(cb) { const assertErrorNotSeen = new Error('should not be seen') const assertError = new Error('test') @@ -52,11 +52,11 @@ t.describe('#requestEnd()', function() { throw assertError }) - flaska.requestEnd(assertErrorNotSeen, ctx) + flaska.__requestEnd(assertErrorNotSeen, ctx) }) let testMethods = ['GET', 'HEAD'] - + testMethods.forEach(function(method) { t.describe(method, function() { t.test('call res and end correctly when dealing with objects', function(cb) { @@ -86,9 +86,9 @@ t.describe('#requestEnd()', function() { status: assertStatus, }, onFinish) ctx.body = assertBody - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) t.test('call res and end correctly when dealing with buffers', function(cb) { @@ -118,9 +118,9 @@ t.describe('#requestEnd()', function() { status: assertStatus, }, onFinish) ctx.body = assertBody - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) t.test('call res and end correctly when dealing with null and no status override', function(cb) { @@ -144,11 +144,11 @@ t.describe('#requestEnd()', function() { status: 200, }, onFinish) ctx.body = assertBody - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) - + t.test('call res and end correctly when dealing with null and status override', function(cb) { const assertStatus = 202 // Calculated manually just in case @@ -170,11 +170,11 @@ t.describe('#requestEnd()', function() { status: assertStatus, }, onFinish) ctx.body = assertBody - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) - + t.test('call res and end correctly when dealing with strings', function(cb) { const assertStatus = 206 // Calculated manually just in case @@ -202,11 +202,11 @@ t.describe('#requestEnd()', function() { status: assertStatus, }, onFinish) ctx.body = assertBody - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) - + t.test('call res and end correctly when dealing with numbers', function(cb) { const assertStatus = 211 // Calculated manually just in case @@ -233,11 +233,11 @@ t.describe('#requestEnd()', function() { status: assertStatus, }, onFinish) ctx.body = assertBody - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) - + if (method === 'GET') { t.test('call handleRequest if body contains it', function(cb) { const assertContentType = 'test/test' @@ -271,11 +271,11 @@ t.describe('#requestEnd()', function() { ctx.body = body fakeStream.pipeline = onFinish body.handleRequest = assertHandle - + let flaska = new Flaska({}, fakerHttp, fakeStream) try { - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) } catch (err) { cb(err) } @@ -304,7 +304,7 @@ t.describe('#requestEnd()', function() { ctx.body = assertBody ctx.type = assertType let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) } else { t.test('call handleRequest if body contains it', function(cb) { @@ -337,11 +337,11 @@ t.describe('#requestEnd()', function() { }, onFinish) ctx.body = body body.handleRequest = assertHandle - + let flaska = new Flaska({}, fakerHttp, fakeStream) try { - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) } catch (err) { cb(err) } @@ -357,7 +357,7 @@ t.describe('#requestEnd()', function() { assert.strictEqual(ctx.headers['Content-Type'], assertType) assert.notOk(ctx.headers['Content-Length']) assert.notOk(body) - + assert.ok(assertBody.destroy.called) assert.ok(ctx.res.writeHead.called) assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) @@ -371,12 +371,12 @@ t.describe('#requestEnd()', function() { ctx.body = assertBody ctx.type = assertType let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) } }) }) - + t.test('call _onerror with error if handleRequest throws error', function() { let body = new FileResponse() const assertError = new Error('Secrets of the Goddess') @@ -393,7 +393,7 @@ t.describe('#requestEnd()', function() { assert.strictEqual(err, assertError) checkCtx.body = assertBody }) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) assert.ok(assertHandle.called) assert.ok(flaska._onerror.called) assert.strictEqual(flaska._onerror.firstCall[0], assertError) @@ -420,7 +420,7 @@ t.describe('#requestEnd()', function() { ctx.type = assertType let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) t.test('call pipe should have default type', function(cb) { @@ -438,7 +438,7 @@ t.describe('#requestEnd()', function() { fakeStream.pipeline = onFinish let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) let tests = [ @@ -462,12 +462,12 @@ t.describe('#requestEnd()', function() { const ctx = createCtx({}) ctx.body = { pipe: function() {}, path: './bla/test/temp.' + test[0] } fakeStream.pipeline = onFinish - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) }) - + t.test('should return immediately if req is finished', function() { let onFinish = function() { throw new Error('should not be called') @@ -476,9 +476,9 @@ t.describe('#requestEnd()', function() { ctx.res.writableEnded = true let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) - + const emptyStatuses = [204, 205, 304] emptyStatuses.forEach(function(status) { @@ -499,9 +499,9 @@ t.describe('#requestEnd()', function() { body: assertNotBody, }, onFinish) ctx.type = assertNotType - + let flaska = new Flaska({}, fakerHttp, fakeStream) - flaska.requestEnd(null, ctx) + flaska.__requestEnd(null, ctx) }) }) }) @@ -518,7 +518,7 @@ t.describe('#requestEnded()', function() { let flaska = new Flaska({}, fakerHttp) flaska._afterCompiled = function() {} - flaska.requestEnded(ctx) + flaska.__requestEnded(ctx) assert.ok(ctx.body.destroy.called) }) @@ -534,7 +534,7 @@ t.describe('#requestEnded()', function() { let flaska = new Flaska({}, fakerHttp) flaska._afterCompiled = function() {} - flaska.requestEnded(ctx) + flaska.__requestEnded(ctx) assert.notOk(ctx.body.destroy.called) }) @@ -550,7 +550,7 @@ t.describe('#requestEnded()', function() { } assert.throws(function() { - flaska.requestEnded(assertCtx) + flaska.__requestEnded(assertCtx) }, /test/) }) @@ -558,14 +558,14 @@ t.describe('#requestEnded()', function() { const assertError = new Error('test') const assertCtx = createCtx() let flaska = new Flaska({}, fakerHttp) - flaska.compile() + flaska.__compile() flaska._afterAsyncCompiled = function(ctx) { assert.strictEqual(ctx, assertCtx) return Promise.resolve().then(function() { return Promise.reject(assertError) }) } - let err = await assert.isRejected(flaska.requestEnded(assertCtx)) + let err = await assert.isRejected(flaska.__requestEnded(assertCtx)) assert.strictEqual(err, assertError) })