From cfd56f83ae9fd6074e04ccc60aee73efc415e424 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Fri, 25 Mar 2022 13:26:13 +0000 Subject: [PATCH] requestEnd: Now properly supports ctx.headers and properly sends all headers to res with status code using writeHead FileResponse: Initial development started to serve files --- flaska.mjs | 32 ++++++++++++------ test/fileResponse.test.mjs | 19 +++++++++++ test/flaska.out.test.mjs | 67 ++++++++++++++++++++++---------------- 3 files changed, 80 insertions(+), 38 deletions(-) create mode 100644 test/fileResponse.test.mjs diff --git a/flaska.mjs b/flaska.mjs index 176b426..a611a1e 100644 --- a/flaska.mjs +++ b/flaska.mjs @@ -277,15 +277,22 @@ export function FormidableHandler(formidable, org = {}) { export class HttpError extends Error { constructor(statusCode, message, body = null) { - super(message); + super(message); - Error.captureStackTrace(this, HttpError); + Error.captureStackTrace(this, HttpError); - let proto = Object.getPrototypeOf(this); - proto.name = 'HttpError'; + let proto = Object.getPrototypeOf(this); + proto.name = 'HttpError'; - this.status = statusCode - this.body = body + this.status = statusCode + this.body = body + } +} + +export class FileResponse { + constructor(filepath, stat) { + this.filepath = filepath + this.stat = stat } } @@ -830,6 +837,7 @@ ctx.state.nonce = nonce; ctx.res.statusCode = ctx.status if (statuses.empty[ctx.status]) { + ctx.res.writeHead(ctx.status, ctx.headers) return ctx.res.end() } @@ -845,20 +853,24 @@ ctx.state.nonce = nonce; ctx.type = found[found.length - 1] } } - ctx.res.setHeader('Content-Type', ctx.type || 'application/octet-stream') + ctx.headers['Content-Type'] = ctx.type || 'application/octet-stream' + + ctx.res.writeHead(ctx.status, ctx.headers) return this.stream.pipeline(body, ctx.res, function() { }) } if (typeof(body) === 'object') { body = JSON.stringify(body) length = Buffer.byteLength(body) - ctx.res.setHeader('Content-Type', 'application/json; charset=utf-8') + ctx.headers['Content-Type'] = 'application/json; charset=utf-8' } else { body = body.toString() length = Buffer.byteLength(body) - ctx.res.setHeader('Content-Type', ctx.type || 'text/plain; charset=utf-8') + ctx.headers['Content-Type'] = ctx.type || 'text/plain; charset=utf-8' } - ctx.res.setHeader('Content-Length', length) + ctx.headers['Content-Length'] = length + + ctx.res.writeHead(ctx.status, ctx.headers) ctx.res.end(body) } diff --git a/test/fileResponse.test.mjs b/test/fileResponse.test.mjs new file mode 100644 index 0000000..dc5ffc6 --- /dev/null +++ b/test/fileResponse.test.mjs @@ -0,0 +1,19 @@ +import { Eltro as t, assert, stub } from 'eltro' +import { FileResponse } from '../flaska.mjs' + +t.test('should add path and stat', function() { + const assertPath = 'some/path/here' + const assertStat = { a: 1 } + + let fileRes = new FileResponse(assertPath, assertStat) + + assert.strictEqual(fileRes.filepath, assertPath) + assert.strictEqual(fileRes.stat, assertStat) +}) + +t.describe('CreateReader()', function() { + t.test('should return fileReader for file with correct seeking', function() { + const stubCreateReadStream = stub() + + }) +}) diff --git a/test/flaska.out.test.mjs b/test/flaska.out.test.mjs index 3ae3fd1..7b601f1 100644 --- a/test/flaska.out.test.mjs +++ b/test/flaska.out.test.mjs @@ -17,13 +17,13 @@ t.describe('#requestEnd()', function() { assert.strictEqual(ctx.status, assertStatus) assert.strictEqual(ctx.body, assertBody) assert.strictEqual(ctx.res.statusCode, assertStatus) - assert.strictEqual(ctx.res.setHeader.callCount, 2) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], 'application/json; charset=utf-8') - assert.strictEqual(ctx.res.setHeader.secondCall[0], 'Content-Length') - assert.strictEqual(ctx.res.setHeader.secondCall[1], assertBodyLength) + assert.strictEqual(ctx.headers['Content-Type'], 'application/json; charset=utf-8') + assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength) assert.ok(body) assert.strictEqual(body, '{"a":1}') + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -72,13 +72,13 @@ t.describe('#requestEnd()', function() { assert.strictEqual(ctx.status, assertStatus) assert.strictEqual(ctx.body, assertBody) assert.strictEqual(ctx.res.statusCode, assertStatus) - assert.strictEqual(ctx.res.setHeader.callCount, 2) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], 'application/json; charset=utf-8') - assert.strictEqual(ctx.res.setHeader.secondCall[0], 'Content-Length') - assert.strictEqual(ctx.res.setHeader.secondCall[1], assertBodyLength) + assert.strictEqual(ctx.headers['Content-Type'], 'application/json; charset=utf-8') + assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength) assert.ok(body) assert.strictEqual(body, '{"a":1}') + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -101,13 +101,13 @@ t.describe('#requestEnd()', function() { assert.strictEqual(ctx.status, assertStatus) assert.strictEqual(ctx.body, assertBody) assert.strictEqual(ctx.res.statusCode, assertStatus) - assert.strictEqual(ctx.res.setHeader.callCount, 2) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], 'text/plain; charset=utf-8') - assert.strictEqual(ctx.res.setHeader.secondCall[0], 'Content-Length') - assert.strictEqual(ctx.res.setHeader.secondCall[1], assertBodyLength) + assert.strictEqual(ctx.headers['Content-Type'], 'text/plain; charset=utf-8') + assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength) assert.ok(body) assert.strictEqual(body, assertBody) + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -130,13 +130,13 @@ t.describe('#requestEnd()', function() { assert.strictEqual(ctx.status, assertStatus) assert.strictEqual(ctx.body, assertBody) assert.strictEqual(ctx.res.statusCode, assertStatus) - assert.strictEqual(ctx.res.setHeader.callCount, 2) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], 'text/plain; charset=utf-8') - assert.strictEqual(ctx.res.setHeader.secondCall[0], 'Content-Length') - assert.strictEqual(ctx.res.setHeader.secondCall[1], assertBodyLength) + assert.strictEqual(ctx.headers['Content-Type'], 'text/plain; charset=utf-8') + assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength) assert.ok(body) assert.strictEqual(body, assertBody.toString()) + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -157,9 +157,11 @@ t.describe('#requestEnd()', function() { try { assert.strictEqual(ctx.status, assertStatus) assert.strictEqual(ctx.res.statusCode, assertStatus) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], assertType) + assert.strictEqual(ctx.headers['Content-Type'], assertType) assert.strictEqual(body, assertBody) + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -182,11 +184,13 @@ t.describe('#requestEnd()', function() { try { assert.strictEqual(ctx.status, assertStatus) assert.strictEqual(ctx.res.statusCode, assertStatus) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], assertType) + assert.strictEqual(ctx.headers['Content-Type'], assertType) assert.strictEqual(source, assertBody) assert.strictEqual(target, ctx.res) assert.strictEqual(typeof(callback), 'function') + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -205,10 +209,12 @@ t.describe('#requestEnd()', function() { let onFinish = function(source, target) { try { assert.strictEqual(ctx.res.statusCode, 200) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], 'application/octet-stream') + assert.strictEqual(ctx.headers['Content-Type'], 'application/octet-stream') assert.strictEqual(source, ctx.body) assert.strictEqual(target, ctx.res) + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -232,10 +238,12 @@ t.describe('#requestEnd()', function() { let onFinish = function(source, target) { try { assert.strictEqual(ctx.res.statusCode, 200) - assert.strictEqual(ctx.res.setHeader.firstCall[0], 'Content-Type') - assert.strictEqual(ctx.res.setHeader.firstCall[1], test[1]) + assert.strictEqual(ctx.headers['Content-Type'], test[1]) assert.strictEqual(source, ctx.body) assert.strictEqual(target, ctx.res) + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) cb() } catch (err) { cb(err) } } @@ -271,6 +279,9 @@ t.describe('#requestEnd()', function() { assert.strictEqual(ctx.status, assertStatus) assert.strictEqual(ctx.res.statusCode, assertStatus) assert.strictEqual(ctx.res.setHeader.callCount, 0) + assert.ok(ctx.res.writeHead.called) + assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status) + assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers) assert.notOk(body) cb() } catch (err) { cb(err) }