Constructor: Support for defaultHeaders was added with default secure options.
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
CSP: Added smart CSP support with nonce support as well. Can generate unique nonce values for each request. CorsHandler: Started development of basic cors handler.
This commit is contained in:
parent
e50e9f8a94
commit
7b682e8e95
8 changed files with 1430 additions and 55 deletions
|
@ -1,2 +1 @@
|
|||
start /B /WAIT /REALTIME node index.js
|
||||
pause
|
||||
start /B /WAIT /REALTIME node index.js
|
|
@ -1,3 +1,4 @@
|
|||
import crypto from 'crypto'
|
||||
import assert from 'assert'
|
||||
import Benchmark from 'benchmarkjs-pretty'
|
||||
import { koaRouter1, koaRouter2 } from './router_koa.js'
|
||||
|
@ -176,7 +177,89 @@ function TestObjectAssign() {
|
|||
ctx.router2 = flaskaRouter2
|
||||
}
|
||||
|
||||
function registerHeader(ctx) {
|
||||
ctx.headers['Server'] = 'nginx/1.16.1'
|
||||
ctx.headers['Date'] = 'Mon, 21 Mar 2022 07:26:01 GMT'
|
||||
ctx.headers['Content-Type'] = 'application/json; charset=utf-8'
|
||||
ctx.headers['Content-Length'] = '1646'
|
||||
ctx.headers['Connection'] = 'keep-alive'
|
||||
ctx.headers['vary'] = 'Origin'
|
||||
ctx.headers['Link'] = '<http://kisildalur.is/api/categories?perPage=1250>; rel="current"; title="Page 1"'
|
||||
ctx.headers['pagination_total'] = '7'
|
||||
ctx.headers['X-Frame-Options'] = 'DENY'
|
||||
ctx.headers['X-Content-Type-Options'] = 'nosniff'
|
||||
}
|
||||
|
||||
function registerHeaderAlt(ctx) {
|
||||
ctx.headers = {
|
||||
'Server': 'nginx/1.16.1',
|
||||
'Date': 'Mon, 21 Mar 2022 07:26:01 GMT',
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'Content-Length': '1646',
|
||||
'Connection': 'keep-alive',
|
||||
'vary': 'Origin',
|
||||
'Link': '<http://kisildalur.is/api/categories?perPage=1250>; rel="current"; title="Page 1"',
|
||||
'pagination_total': '7',
|
||||
'X-Frame-Options': 'DENY',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
}
|
||||
}
|
||||
|
||||
let baseHeaders = {
|
||||
'Server': 'nginx/1.16.1',
|
||||
'Date': 'Mon, 21 Mar 2022 07:26:01 GMT',
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'Content-Length': '1646',
|
||||
'Connection': 'keep-alive',
|
||||
'vary': 'Origin',
|
||||
'Link': '<http://kisildalur.is/api/categories?perPage=1250>; rel="current"; title="Page 1"',
|
||||
'pagination_total': '7',
|
||||
'X-Frame-Options': 'DENY',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
}
|
||||
let keys = Object.keys(baseHeaders)
|
||||
|
||||
|
||||
return new Benchmark.default('test different method to initialize objects)')
|
||||
.add('[HEADERS] Object.assign()', function() {
|
||||
let ctx = {
|
||||
headers: {}
|
||||
}
|
||||
Object.assign(ctx.headers, baseHeaders)
|
||||
// assert.notStrictEqual(ctx.headers, baseHeaders)
|
||||
})
|
||||
.add('[HEADERS] ecmascript spread', function() {
|
||||
let ctx = {
|
||||
headers: {
|
||||
...baseHeaders
|
||||
}
|
||||
}
|
||||
// assert.notStrictEqual(ctx.headers, baseHeaders)
|
||||
})
|
||||
.add('[HEADERS] Basic clone lol', function() {
|
||||
let ctx = {
|
||||
headers: {}
|
||||
}
|
||||
for (let key of keys) {
|
||||
ctx.headers[key] = baseHeaders[key]
|
||||
}
|
||||
// assert.notStrictEqual(ctx.headers, baseHeaders)
|
||||
})
|
||||
.add('[HEADERS] Use register function', function() {
|
||||
let ctx = {
|
||||
headers: {}
|
||||
}
|
||||
registerHeader(ctx)
|
||||
// assert.notStrictEqual(ctx.headers, baseHeaders)
|
||||
})
|
||||
.add('[HEADERS] Use register function ALT', function() {
|
||||
let ctx = {
|
||||
headers: {}
|
||||
}
|
||||
registerHeaderAlt(ctx)
|
||||
// assert.notStrictEqual(ctx.headers, baseHeaders)
|
||||
})
|
||||
/*
|
||||
.add('Object.assign()', function() {
|
||||
let ctx = {
|
||||
req: req,
|
||||
|
@ -196,7 +279,7 @@ function TestObjectAssign() {
|
|||
register3(ctx)
|
||||
ctx.log.info()
|
||||
})
|
||||
/*.add('Object.create() all props', function() {
|
||||
.add('Object.create() all props', function() {
|
||||
let ctx = Object.create({}, propMakerAlt)
|
||||
ctx.log.info()
|
||||
})
|
||||
|
@ -212,7 +295,100 @@ function TestObjectAssign() {
|
|||
let ctx = { }
|
||||
Object.defineProperties(ctx, propMakerAlt)
|
||||
ctx.log.info()
|
||||
})*/
|
||||
})
|
||||
*/
|
||||
.run()
|
||||
.then(function() {}, function(e) {
|
||||
console.error('error:', e)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
function TestGenerateRandomString() {
|
||||
|
||||
return new Benchmark.default('test different method to generate random string)')
|
||||
.add('crypto.randomBytes(16)', function() {
|
||||
for (let i = 0; i < 25; i++) {
|
||||
crypto.randomBytes(16).toString('base64')
|
||||
}
|
||||
})
|
||||
.add('crypto.randomBytes(32)', function() {
|
||||
for (let i = 0; i < 25; i++) {
|
||||
crypto.randomBytes(32).toString('base64')
|
||||
}
|
||||
})
|
||||
.add('random (22 characters long)', function() {
|
||||
for (let i = 0; i < 25; i++) {
|
||||
let out = Math.random().toString(36).substring(2, 24)
|
||||
+ Math.random().toString(36).substring(2, 24)
|
||||
}
|
||||
})
|
||||
.add('random (44 characters long)', function() {
|
||||
for (let i = 0; i < 25; i++) {
|
||||
let out = Math.random().toString(36).substring(2, 24)
|
||||
+ Math.random().toString(36).substring(2, 24)
|
||||
+ Math.random().toString(36).substring(2, 24)
|
||||
+ Math.random().toString(36).substring(2, 24)
|
||||
}
|
||||
})
|
||||
.run()
|
||||
.then(function() {}, function(e) {
|
||||
console.error('error:', e)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
function TestArrayReduce() {
|
||||
return new Benchmark.default('test different method to reduce array)')
|
||||
.add('currIndex', function() {
|
||||
const arr1 = new Array(100)
|
||||
|
||||
for (let i = 0; i < arr1.length; i++) {
|
||||
arr1[i] = 'a'
|
||||
}
|
||||
|
||||
let currIndex = arr1.length - 1
|
||||
|
||||
let out = ''
|
||||
while (currIndex >= 0) {
|
||||
out += arr1[currIndex]
|
||||
currIndex--
|
||||
}
|
||||
})
|
||||
.add('crypto.randomBytes(32)', function() {
|
||||
const arr1 = new Array(100)
|
||||
|
||||
for (let i = 0; i < arr1.length; i++) {
|
||||
arr1[i] = 'a'
|
||||
}
|
||||
|
||||
let out = ''
|
||||
while (arr1.length > 0) {
|
||||
out += arr1.splice(0, 1)[0]
|
||||
}
|
||||
})
|
||||
.run()
|
||||
.then(function() {}, function(e) {
|
||||
console.error('error:', e)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
function TestStringCombination() {
|
||||
let val1 = 'some'
|
||||
let val2 = 'text'
|
||||
let val3 = 'gose'
|
||||
let val4 = 'here'
|
||||
|
||||
return new Benchmark.default('test different method to combine string)')
|
||||
.add('ES6 with variable', function() {
|
||||
let out = `Hello my friend ${val1} this goes to ${val2} all my homies ${val3} over at my ${val4} house`
|
||||
return out
|
||||
})
|
||||
.add('String concatenation', function() {
|
||||
let out = 'Hello my friend ' + val1 + ' this goes to ' + val2 + ' all my homies ' + val3 + ' over at my ' + val4 + ' house'
|
||||
return out
|
||||
})
|
||||
.run()
|
||||
.then(function() {}, function(e) {
|
||||
console.error('error:', e)
|
||||
|
@ -345,8 +521,8 @@ function TestLargeParamLargeUrlRoute() {
|
|||
})
|
||||
}
|
||||
|
||||
/*
|
||||
TestSmallStaticRoute()
|
||||
// TestObjectAssign()
|
||||
// TestPromiseCreators()
|
||||
.then(function() {
|
||||
return TestSmallParamRoute()
|
||||
|
@ -362,4 +538,12 @@ TestSmallStaticRoute()
|
|||
})
|
||||
.then(function() {
|
||||
process.exit(0)
|
||||
})
|
||||
})*/
|
||||
|
||||
// TestObjectAssign()
|
||||
// TestGenerateRandomString()
|
||||
// TestArrayReduce()
|
||||
TestStringCombination()
|
||||
.then(function() {
|
||||
process.exit(0)
|
||||
})
|
725
benchmark/package-lock.json
generated
725
benchmark/package-lock.json
generated
|
@ -1,8 +1,731 @@
|
|||
{
|
||||
"name": "benchmark",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "benchmark",
|
||||
"version": "1.0.0",
|
||||
"license": "WTFPL",
|
||||
"dependencies": {
|
||||
"benchmarkjs-pretty": "^2.0.0",
|
||||
"express": "^4.17.1",
|
||||
"koa-router": "^8.0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/benchmark": {
|
||||
"version": "1.0.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/benchmark/-/benchmark-1.0.31.tgz",
|
||||
"integrity": "sha512-F6fVNOkGEkSdo/19yWYOwVKGvzbTeWkR/XQYBKtGBQ9oGRjBN9f/L4aJI4sDcVPJO58Y1CJZN8va9V2BhrZapA=="
|
||||
},
|
||||
"node_modules/@types/chalk": {
|
||||
"version": "0.4.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz",
|
||||
"integrity": "sha1-ox10JBprHtu5c8822XooloNKUfk="
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"node_modules/benchmark": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz",
|
||||
"integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4",
|
||||
"platform": "^1.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/benchmarkjs-pretty": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/benchmarkjs-pretty/-/benchmarkjs-pretty-2.0.0.tgz",
|
||||
"integrity": "sha512-t5a+ztdAuim1HPEbQwBELN9ugqe5WCSbjwPh79olqS+zgw44Bi/3qPz472LNPIfXlTernAo+meL8KULaXuWAeQ==",
|
||||
"dependencies": {
|
||||
"@types/benchmark": "^1.0.30",
|
||||
"@types/chalk": "^0.4.31",
|
||||
"benchmark": "^2.1.4",
|
||||
"chalk": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.0",
|
||||
"content-type": "~1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "~2.3.0",
|
||||
"qs": "6.7.0",
|
||||
"raw-body": "2.4.0",
|
||||
"type-is": "~1.6.17"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser/node_modules/http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser/node_modules/inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"node_modules/body-parser/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "5.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.7",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.19.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "~1.1.2",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.5",
|
||||
"qs": "6.7.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.1.2",
|
||||
"send": "0.17.1",
|
||||
"serve-static": "1.14.1",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": "~1.5.0",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
|
||||
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "~1.5.0",
|
||||
"unpipe": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
|
||||
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||
},
|
||||
"node_modules/koa-compose": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
|
||||
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
|
||||
},
|
||||
"node_modules/koa-router": {
|
||||
"version": "8.0.8",
|
||||
"resolved": "https://registry.npmjs.org/koa-router/-/koa-router-8.0.8.tgz",
|
||||
"integrity": "sha512-2rNF2cgu/EWi/NV8GlBE5+H/QBoaof83X6Z0dULmalkbt7W610/lyP2EOLVqVrUUFfjsVWL/Ju5TVBcGJDY9XQ==",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
"http-errors": "^1.7.3",
|
||||
"koa-compose": "^4.1.0",
|
||||
"methods": "^1.1.2",
|
||||
"path-to-regexp": "1.x",
|
||||
"urijs": "^1.19.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/koa-router/node_modules/path-to-regexp": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
|
||||
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
|
||||
"dependencies": {
|
||||
"isarray": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
},
|
||||
"node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||
},
|
||||
"node_modules/methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.26",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.43.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||
"dependencies": {
|
||||
"ee-first": "1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
||||
},
|
||||
"node_modules/platform": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz",
|
||||
"integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q=="
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
||||
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
|
||||
"dependencies": {
|
||||
"forwarded": "~0.1.2",
|
||||
"ipaddr.js": "1.9.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
|
||||
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.0",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body/node_modules/http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body/node_modules/inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/debug/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node_modules/send/node_modules/ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
|
||||
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
|
||||
"dependencies": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"dependencies": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/urijs": {
|
||||
"version": "1.19.2",
|
||||
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz",
|
||||
"integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w=="
|
||||
},
|
||||
"node_modules/utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/benchmark": {
|
||||
"version": "1.0.31",
|
||||
|
|
129
flaska.mjs
129
flaska.mjs
|
@ -1,4 +1,5 @@
|
|||
import os from 'os'
|
||||
import crypto from 'crypto'
|
||||
import path from 'path'
|
||||
import http from 'http'
|
||||
import stream from 'stream'
|
||||
|
@ -128,6 +129,28 @@ export function JsonHandler(org = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
export function CorsHandler(opts = {}) {
|
||||
const options = {
|
||||
allowedMethods: opts.allowedMethods || 'GET,HEAD,PUT,POST,DELETE,PATCH',
|
||||
allowedHeaders: opts.allowedHeaders,
|
||||
openerPolicy: 'same-origin',
|
||||
resourcePolicy: 'same-origin',
|
||||
embedderPolicy: 'require-corp',
|
||||
}
|
||||
|
||||
return function(ctx) {
|
||||
let origin = ctx.req.headers['origin']
|
||||
let reqHeaders = options.allowedHeaders || ctx.req.headers['access-control-request-headers']
|
||||
|
||||
ctx.headers['Access-Control-Allow-Origin'] = origin
|
||||
ctx.headers['Access-Control-Allow-Methods'] = options.allowedMethods
|
||||
if (reqHeaders && options.allowedHeaders !== false) {
|
||||
ctx.headers['Access-Control-Allow-Headers'] = reqHeaders
|
||||
}
|
||||
ctx.status = 204
|
||||
}
|
||||
}
|
||||
|
||||
export function FormidableHandler(formidable, org = {}) {
|
||||
let lastDateString = ''
|
||||
let incrementor = 1
|
||||
|
@ -420,7 +443,7 @@ export class FlaskaRouter {
|
|||
* Flaska
|
||||
*/
|
||||
export class Flaska {
|
||||
constructor(opts, orgHttp = http, orgStream = stream) {
|
||||
constructor(opts = {}, orgHttp = http, orgStream = stream) {
|
||||
this._before = []
|
||||
this._beforeCompiled = null
|
||||
this._beforeAsync = []
|
||||
|
@ -430,10 +453,12 @@ export class Flaska {
|
|||
this._afterAsync = []
|
||||
this._afterAsyncCompiled = null
|
||||
this._on404 = function(ctx) {
|
||||
ctx.status = 404
|
||||
ctx.body = {
|
||||
status: 404,
|
||||
message: statuses[404],
|
||||
if (ctx.body == null && ctx.status !== 204) {
|
||||
ctx.status = 404
|
||||
ctx.body = {
|
||||
status: 404,
|
||||
message: statuses[404],
|
||||
}
|
||||
}
|
||||
}
|
||||
this._backuperror = this._onerror = function(err, ctx) {
|
||||
|
@ -465,17 +490,91 @@ export class Flaska {
|
|||
ctx.log.error(err)
|
||||
}
|
||||
|
||||
let options = opts || {}
|
||||
|
||||
this.log = options.log || {
|
||||
fatal: console.error.bind(console),
|
||||
error: console.error.bind(console),
|
||||
warn: console.log.bind(console),
|
||||
info: console.log.bind(console),
|
||||
debug: console.debug.bind(console),
|
||||
trace: console.debug.bind(console),
|
||||
log: console.log.bind(console),
|
||||
let options = {
|
||||
defaultHeaders: opts.defaultHeaders || {
|
||||
'Server': 'Flaska',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'Content-Security-Policy': `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; object-src 'none'; frame-ancestors 'none'`,
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Resource-Policy': 'same-origin',
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
},
|
||||
log: opts.log || {
|
||||
fatal: console.error.bind(console),
|
||||
error: console.error.bind(console),
|
||||
warn: console.log.bind(console),
|
||||
info: console.log.bind(console),
|
||||
debug: console.debug.bind(console),
|
||||
trace: console.debug.bind(console),
|
||||
log: console.log.bind(console),
|
||||
},
|
||||
nonce: opts.nonce || [],
|
||||
nonceCacheLength: opts.nonceCacheLength || 25
|
||||
}
|
||||
|
||||
if (!options.defaultHeaders && options.nonce.length) {
|
||||
// throw error
|
||||
}
|
||||
|
||||
let headerKeys = Object.keys(options.defaultHeaders)
|
||||
let constructFunction = ''
|
||||
|
||||
if (options.nonce.length) {
|
||||
this._nonces = new Array(options.nonceCacheLength)
|
||||
this._noncesIndex = this._nonces.length - 1
|
||||
|
||||
for (let i = 0; i < this._nonces.length; i++) {
|
||||
this._nonces[i] = crypto.randomBytes(16).toString('base64')
|
||||
}
|
||||
|
||||
constructFunction += `
|
||||
let nonce = this._nonces[this._noncesIndex] || crypto.randomBytes(16).toString('base64');
|
||||
this._noncesIndex--;
|
||||
ctx.state.nonce = nonce;
|
||||
`
|
||||
}
|
||||
|
||||
constructFunction += 'ctx.headers = {'
|
||||
for (let key of headerKeys) {
|
||||
if (key === 'Content-Security-Policy' && options.nonce.length) {
|
||||
let groups = options.defaultHeaders[key].split(';')
|
||||
for (let ni = 0; ni < options.nonce.length; ni++) {
|
||||
let found = false
|
||||
for (let x = 0; x < groups.length; x++) {
|
||||
if (groups[x].trim().startsWith(options.nonce[ni])) {
|
||||
groups[x] = groups[x].trimEnd() + ` 'nonce-$'`
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
groups.push(` ${options.nonce[ni]} 'nonce-$'`)
|
||||
}
|
||||
}
|
||||
groups = groups.join(';').replace(/\'/g, "\\'").split('$')
|
||||
constructFunction += `'${key}': '${groups.join(`' + nonce + '`)}',`
|
||||
} else {
|
||||
constructFunction += `'${key}': '${options.defaultHeaders[key].replace(/\'/g, "\\'")}',`
|
||||
}
|
||||
}
|
||||
constructFunction += '};'
|
||||
|
||||
// console.log(constructFunction)
|
||||
|
||||
if (options.nonce.length) {
|
||||
this.before(new Function('crypto', 'ctx', constructFunction).bind(this, crypto))
|
||||
this.after(new Function('crypto', 'ctx', `
|
||||
this._noncesIndex = Math.max(this._noncesIndex, -1);
|
||||
if (this._noncesIndex < this._nonces.length - 1) {
|
||||
this._noncesIndex++;
|
||||
this._nonces[this._noncesIndex] = crypto.randomBytes(16).toString('base64');
|
||||
}
|
||||
`).bind(this, crypto))
|
||||
} else {
|
||||
this.before(new Function('ctx', constructFunction).bind(this))
|
||||
}
|
||||
|
||||
this.log = options.log
|
||||
this.http = orgHttp
|
||||
this.stream = orgStream
|
||||
this.server = null
|
||||
|
|
|
@ -4,34 +4,250 @@ import { createCtx, fakeHttp } from './helper.mjs'
|
|||
|
||||
const faker = fakeHttp()
|
||||
|
||||
t.test('should be able to override the http', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.strictEqual(flaska.http, faker)
|
||||
t.describe('#constructor', function() {
|
||||
t.test('should be able to override the http', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.strictEqual(flaska.http, faker)
|
||||
})
|
||||
|
||||
t.test('it should have all the common verbs', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.ok(flaska.get)
|
||||
assert.strictEqual(typeof(flaska.get), 'function')
|
||||
assert.ok(flaska.post)
|
||||
assert.strictEqual(typeof(flaska.post), 'function')
|
||||
assert.ok(flaska.put)
|
||||
assert.strictEqual(typeof(flaska.put), 'function')
|
||||
assert.ok(flaska.delete)
|
||||
assert.strictEqual(typeof(flaska.delete), 'function')
|
||||
assert.ok(flaska.options)
|
||||
assert.strictEqual(typeof(flaska.options), 'function')
|
||||
assert.ok(flaska.patch)
|
||||
assert.strictEqual(typeof(flaska.patch), 'function')
|
||||
})
|
||||
|
||||
t.test('the verbs GET and HEAD should be identical', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.ok(flaska.get)
|
||||
assert.strictEqual(typeof(flaska.get), 'function')
|
||||
assert.notOk(flaska.head)
|
||||
assert.ok(flaska.routers['HEAD'])
|
||||
assert.strictEqual(flaska.routers['GET'], flaska.routers['HEAD'])
|
||||
})
|
||||
|
||||
t.test('should have before default header generator', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.strictEqual(flaska._before.length, 1)
|
||||
|
||||
let ctx = {}
|
||||
|
||||
flaska._before[0](ctx)
|
||||
|
||||
assert.deepStrictEqual(ctx.headers, {
|
||||
'Server': 'Flaska',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'Content-Security-Policy': `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; object-src 'none'; frame-ancestors 'none'`,
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Resource-Policy': 'same-origin',
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
})
|
||||
assert.strictEqual(flaska._after.length, 0)
|
||||
})
|
||||
|
||||
t.test('should have before ready setting headers on context if defaultHeaders is specified', function() {
|
||||
const defaultHeaders = {
|
||||
'Server': 'nginx/1.16.1',
|
||||
'Date': 'Mon, 21 Mar\' 2022 07:26:01 GMT',
|
||||
'Content-Type': 'applicat"ion/json; charset=utf-8',
|
||||
'Content-Length': '1646',
|
||||
'Connection': 'keep-alive',
|
||||
'vary': 'Origin',
|
||||
'Link': 'Link goes here',
|
||||
'X-Frame-Options': 'DENY',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
}
|
||||
let flaska = new Flaska({
|
||||
defaultHeaders: defaultHeaders,
|
||||
}, faker)
|
||||
assert.strictEqual(flaska._before.length, 1)
|
||||
|
||||
let ctx = {}
|
||||
|
||||
flaska._before[0](ctx)
|
||||
|
||||
assert.notStrictEqual(ctx.headers, defaultHeaders)
|
||||
assert.deepStrictEqual(ctx.headers, defaultHeaders)
|
||||
assert.strictEqual(flaska._after.length, 0)
|
||||
})
|
||||
})
|
||||
|
||||
t.test('it should have all the common verbs', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.ok(flaska.get)
|
||||
assert.strictEqual(typeof(flaska.get), 'function')
|
||||
assert.ok(flaska.post)
|
||||
assert.strictEqual(typeof(flaska.post), 'function')
|
||||
assert.ok(flaska.put)
|
||||
assert.strictEqual(typeof(flaska.put), 'function')
|
||||
assert.ok(flaska.delete)
|
||||
assert.strictEqual(typeof(flaska.delete), 'function')
|
||||
assert.ok(flaska.options)
|
||||
assert.strictEqual(typeof(flaska.options), 'function')
|
||||
assert.ok(flaska.patch)
|
||||
assert.strictEqual(typeof(flaska.patch), 'function')
|
||||
})
|
||||
t.describe('#_nonce', function() {
|
||||
t.test('should support nonce parameter with cached pre-filled entries', function() {
|
||||
let flaska = new Flaska({
|
||||
nonce: ['script-src', 'style-src'],
|
||||
}, faker)
|
||||
|
||||
t.test('the verbs GET and HEAD should be identical', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.ok(flaska.get)
|
||||
assert.strictEqual(typeof(flaska.get), 'function')
|
||||
assert.notOk(flaska.head)
|
||||
assert.ok(flaska.routers['HEAD'])
|
||||
assert.strictEqual(flaska.routers['GET'], flaska.routers['HEAD'])
|
||||
assert.ok(flaska._nonces)
|
||||
assert.strictEqual(flaska._noncesIndex + 1, flaska._nonces.length)
|
||||
assert.strictEqual(flaska._nonces.length, 25)
|
||||
assert.ok(flaska._nonces[flaska._noncesIndex])
|
||||
|
||||
//Check they're all unique
|
||||
let set = new Set()
|
||||
flaska._nonces.forEach(function(entry) {
|
||||
set.add(entry)
|
||||
})
|
||||
assert.strictEqual(set.size, flaska._nonces.length)
|
||||
|
||||
let ctx = createCtx()
|
||||
|
||||
assert.notOk(ctx.state.nonce)
|
||||
|
||||
let oldIndex = flaska._noncesIndex
|
||||
|
||||
flaska._before[0](ctx)
|
||||
|
||||
assert.ok(ctx.state.nonce)
|
||||
assert.strictEqual(flaska._noncesIndex, oldIndex - 1)
|
||||
assert.strictEqual(flaska._nonces[oldIndex], ctx.state.nonce)
|
||||
|
||||
assert.deepStrictEqual(ctx.headers, {
|
||||
'Server': 'Flaska',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'Content-Security-Policy': `default-src 'self'; style-src 'self' 'unsafe-inline' 'nonce-${ctx.state.nonce}'; img-src * data: blob:; object-src 'none'; frame-ancestors 'none'; script-src 'nonce-${ctx.state.nonce}'`,
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Resource-Policy': 'same-origin',
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should always return nonce values even if it runs out in cache', function() {
|
||||
let flaska = new Flaska({
|
||||
nonce: ['script-src'],
|
||||
nonceCacheLength: 5,
|
||||
}, faker)
|
||||
let ctx = createCtx()
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
let nextNonce = flaska._nonces[flaska._noncesIndex]
|
||||
flaska._before[0](ctx)
|
||||
assert.strictEqual(ctx.state.nonce, nextNonce)
|
||||
assert.strictEqual(ctx.headers['Content-Security-Policy'], `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; object-src 'none'; frame-ancestors 'none'; script-src 'nonce-${ctx.state.nonce}'`)
|
||||
}
|
||||
|
||||
assert.notOk(flaska._nonces[flaska._noncesIndex])
|
||||
|
||||
flaska._before[0](ctx)
|
||||
|
||||
assert.notOk(flaska._nonces[flaska._noncesIndex])
|
||||
assert.ok(ctx.state.nonce)
|
||||
|
||||
for (let i = 0; i < flaska._nonces.length; i++) {
|
||||
assert.notStrictEqual(ctx.state.nonce, flaska._nonces[i])
|
||||
}
|
||||
|
||||
assert.strictEqual(ctx.headers['Content-Security-Policy'], `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; object-src 'none'; frame-ancestors 'none'; script-src 'nonce-${ctx.state.nonce}'`)
|
||||
})
|
||||
|
||||
t.test('should have after that regenerates lost hashes', function() {
|
||||
let flaska = new Flaska({
|
||||
nonce: ['script-src'],
|
||||
nonceCacheLength: 5,
|
||||
}, faker)
|
||||
let ctx = createCtx()
|
||||
|
||||
assert.strictEqual(flaska._after.length, 1)
|
||||
|
||||
//Check they're all unique
|
||||
let set = new Set()
|
||||
flaska._nonces.forEach(function(entry) {
|
||||
set.add(entry)
|
||||
})
|
||||
assert.strictEqual(set.size, 5)
|
||||
|
||||
flaska._before[0](ctx)
|
||||
flaska._before[0](ctx)
|
||||
flaska._before[0](ctx)
|
||||
|
||||
assert.strictEqual(flaska._noncesIndex, 1)
|
||||
|
||||
flaska._after[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, 2)
|
||||
set.add(flaska._nonces[flaska._noncesIndex])
|
||||
assert.strictEqual(set.size, 6)
|
||||
|
||||
flaska._after[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, 3)
|
||||
set.add(flaska._nonces[flaska._noncesIndex])
|
||||
assert.strictEqual(set.size, 7)
|
||||
|
||||
flaska._after[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, 4)
|
||||
set.add(flaska._nonces[flaska._noncesIndex])
|
||||
assert.strictEqual(set.size, 8)
|
||||
|
||||
flaska._after[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, 4)
|
||||
set.add(flaska._nonces[flaska._noncesIndex])
|
||||
assert.strictEqual(set.size, 8)
|
||||
})
|
||||
|
||||
t.test('after should not generate keys outside range', function() {
|
||||
let flaska = new Flaska({
|
||||
nonce: ['script-src'],
|
||||
nonceCacheLength: 2,
|
||||
}, faker)
|
||||
let ctx = createCtx()
|
||||
|
||||
assert.strictEqual(flaska._after.length, 1)
|
||||
|
||||
//Check they're all unique
|
||||
let set = new Set()
|
||||
flaska._nonces.forEach(function(entry) {
|
||||
set.add(entry)
|
||||
})
|
||||
assert.strictEqual(set.size, 2)
|
||||
|
||||
flaska._before[0](ctx)
|
||||
flaska._before[0](ctx)
|
||||
|
||||
assert.strictEqual(flaska._noncesIndex, -1)
|
||||
|
||||
flaska._before[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, -2)
|
||||
set.add(ctx.state.nonce)
|
||||
assert.strictEqual(set.size, 3)
|
||||
|
||||
flaska._before[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, -3)
|
||||
set.add(ctx.state.nonce)
|
||||
assert.strictEqual(set.size, 4)
|
||||
|
||||
flaska._before[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, -4)
|
||||
set.add(ctx.state.nonce)
|
||||
assert.strictEqual(set.size, 5)
|
||||
|
||||
assert.strictEqual(Object.keys(flaska._nonces).length, 2)
|
||||
|
||||
flaska._after[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, 0)
|
||||
set.add(flaska._nonces[flaska._noncesIndex])
|
||||
assert.strictEqual(set.size, 6)
|
||||
assert.strictEqual(Object.keys(flaska._nonces).length, 2)
|
||||
|
||||
flaska._after[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, 1)
|
||||
set.add(flaska._nonces[flaska._noncesIndex])
|
||||
assert.strictEqual(set.size, 7)
|
||||
assert.strictEqual(Object.keys(flaska._nonces).length, 2)
|
||||
|
||||
flaska._after[0](ctx)
|
||||
assert.strictEqual(flaska._noncesIndex, 1)
|
||||
set.add(flaska._nonces[flaska._noncesIndex])
|
||||
assert.strictEqual(set.size, 7)
|
||||
assert.strictEqual(Object.keys(flaska._nonces).length, 2)
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#log', function() {
|
||||
|
@ -108,11 +324,6 @@ specialHandlers.forEach(function(type) {
|
|||
})
|
||||
|
||||
t.describe('_on404', function() {
|
||||
t.test('a valid function', function() {
|
||||
let flaska = new Flaska({}, faker)
|
||||
assert.strictEqual(typeof(flaska._on404), 'function')
|
||||
})
|
||||
|
||||
t.test('default valid handling of context', function() {
|
||||
let ctx = createCtx()
|
||||
let flaska = new Flaska({}, faker)
|
||||
|
@ -123,6 +334,28 @@ t.describe('_on404', function() {
|
|||
message: 'Not Found',
|
||||
})
|
||||
})
|
||||
|
||||
t.test('should do nothing if body is not null', function() {
|
||||
const assertBody = { a: 1 }
|
||||
let ctx = createCtx()
|
||||
let flaska = new Flaska({}, faker)
|
||||
|
||||
ctx.body = assertBody
|
||||
flaska._on404(ctx)
|
||||
assert.strictEqual(ctx.status, 200)
|
||||
assert.strictEqual(ctx.body, assertBody)
|
||||
})
|
||||
|
||||
t.test('should do nothing if body is null but status is 204', function() {
|
||||
let ctx = createCtx()
|
||||
let flaska = new Flaska({}, faker)
|
||||
|
||||
ctx.status = 204
|
||||
ctx.body = null
|
||||
flaska._on404(ctx)
|
||||
assert.strictEqual(ctx.status, 204)
|
||||
assert.strictEqual(ctx.body, null)
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('_onerror', function() {
|
||||
|
@ -317,8 +550,8 @@ t.describe('#before()', function() {
|
|||
let flaska = new Flaska({}, faker)
|
||||
assert.ok(flaska._before)
|
||||
flaska.before(assertFunction)
|
||||
assert.strictEqual(flaska._before.length, 1)
|
||||
assert.strictEqual(flaska._before[0], assertFunction)
|
||||
assert.strictEqual(flaska._before.length, 2)
|
||||
assert.strictEqual(flaska._before[1], assertFunction)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -153,6 +153,14 @@ t.describe('#requestStart()', function() {
|
|||
assert.ok(ctx.query.get)
|
||||
assert.ok(ctx.query.set)
|
||||
assert.ok(ctx.query.delete)
|
||||
assert.deepStrictEqual(ctx.headers, {
|
||||
'Server': 'Flaska',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'Content-Security-Policy': `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; object-src 'none'; frame-ancestors 'none'`,
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Resource-Policy': 'same-origin',
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
})
|
||||
cb()
|
||||
} catch (err) { cb(err) }
|
||||
}
|
||||
|
@ -163,6 +171,41 @@ t.describe('#requestStart()', function() {
|
|||
}), createRes())
|
||||
})
|
||||
|
||||
t.test('correctly adds default headers', function(cb) {
|
||||
const assertError = new Error('test')
|
||||
const defaultHeaders = {
|
||||
'Test': 'Asdf',
|
||||
'Herp': 'Derp',
|
||||
}
|
||||
let flaska = new Flaska({
|
||||
defaultHeaders: defaultHeaders,
|
||||
}, faker)
|
||||
flaska.compile()
|
||||
|
||||
flaska.routers.test = {
|
||||
match: function(path) {
|
||||
throw assertError
|
||||
}
|
||||
}
|
||||
|
||||
flaska.requestEnd = function(err, ctx) {
|
||||
if (err && err !== assertError) return cb(err)
|
||||
|
||||
try {
|
||||
assert.ok(err)
|
||||
assert.strictEqual(err, assertError)
|
||||
assert.notStrictEqual(ctx.headers, defaultHeaders)
|
||||
assert.deepStrictEqual(ctx.headers, defaultHeaders)
|
||||
cb()
|
||||
} catch (err) { cb(err) }
|
||||
}
|
||||
|
||||
flaska.requestStart(createReq({
|
||||
url: '/',
|
||||
method: 'test',
|
||||
}), createRes())
|
||||
})
|
||||
|
||||
t.test('calls correct router with correct url and context if beforeAsync', function(cb) {
|
||||
const assertError = new Error('test')
|
||||
const assertMethod = 'test'
|
||||
|
|
|
@ -24,6 +24,7 @@ export function fakeHttp(inj1, inj2) {
|
|||
|
||||
export function createReq(def) {
|
||||
return defaults(def, {
|
||||
headers: {},
|
||||
on: spy(),
|
||||
})
|
||||
}
|
||||
|
@ -53,6 +54,7 @@ export function createCtx(def, endHandler) {
|
|||
body: null,
|
||||
type: null,
|
||||
length: null,
|
||||
headers: {},
|
||||
log: {
|
||||
error: spy(),
|
||||
info: spy(),
|
||||
|
|
|
@ -2,7 +2,7 @@ import os from 'os'
|
|||
import path from 'path'
|
||||
import { Buffer } from 'buffer'
|
||||
import { Eltro as t, assert, stub} from 'eltro'
|
||||
import { QueryHandler, JsonHandler, FormidableHandler, HttpError } from '../flaska.mjs'
|
||||
import { QueryHandler, JsonHandler, FormidableHandler, HttpError, CorsHandler } from '../flaska.mjs'
|
||||
import { createCtx } from './helper.mjs'
|
||||
import { finished } from 'stream'
|
||||
import { setTimeout } from 'timers/promises'
|
||||
|
@ -29,6 +29,98 @@ t.describe('#QueryHandler()', function() {
|
|||
})
|
||||
})
|
||||
|
||||
|
||||
t.describe('#CorsHandler()', function() {
|
||||
let corsHandler
|
||||
let ctx
|
||||
|
||||
t.beforeEach(function() {
|
||||
ctx = createCtx()
|
||||
})
|
||||
|
||||
t.test('should return a handler', function() {
|
||||
corsHandler = CorsHandler()
|
||||
assert.strictEqual(typeof(corsHandler), 'function')
|
||||
})
|
||||
|
||||
t.test('should set status and headers', function() {
|
||||
const assertOrigin = 'http://my.site.here'
|
||||
const assertRequestHeaders = 'asdf,foobar'
|
||||
|
||||
corsHandler = CorsHandler({
|
||||
allowedOrigins: [assertOrigin],
|
||||
})
|
||||
ctx.method = 'OPTIONS'
|
||||
ctx.req.headers['origin'] = assertOrigin
|
||||
ctx.req.headers['access-control-request-method'] = 'GET'
|
||||
ctx.req.headers['access-control-request-headers'] = assertRequestHeaders
|
||||
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Origin'])
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Methods'])
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Headers'])
|
||||
|
||||
corsHandler(ctx)
|
||||
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Origin'], assertOrigin)
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Methods'], 'GET,HEAD,PUT,POST,DELETE,PATCH')
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Headers'], assertRequestHeaders)
|
||||
assert.strictEqual(ctx.status, 204)
|
||||
})
|
||||
|
||||
t.test('should support custom allowed methods and headers', function() {
|
||||
const assertOrigin = 'http://my.site.here'
|
||||
const assertAllowedMethods = 'GET,HEAD'
|
||||
const assertAllowedHeaders = 'test1,test2'
|
||||
|
||||
corsHandler = CorsHandler({
|
||||
allowedOrigins: [assertOrigin],
|
||||
allowedMethods: assertAllowedMethods,
|
||||
allowedHeaders: assertAllowedHeaders,
|
||||
})
|
||||
ctx.method = 'OPTIONS'
|
||||
ctx.req.headers['origin'] = assertOrigin
|
||||
ctx.req.headers['access-control-request-method'] = 'GET'
|
||||
ctx.req.headers['access-control-request-headers'] = 'asdfasdfasdfsfad'
|
||||
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Origin'])
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Methods'])
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Headers'])
|
||||
|
||||
corsHandler(ctx)
|
||||
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Origin'], assertOrigin)
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Methods'], assertAllowedMethods)
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Headers'], assertAllowedHeaders)
|
||||
assert.strictEqual(ctx.status, 204)
|
||||
})
|
||||
|
||||
t.test('should not set any allowed headers if allowedHeaders is explicitly false', function() {
|
||||
const assertOrigin = 'http://my.site.here'
|
||||
const assertAllowedMethods = 'GET,HEAD'
|
||||
|
||||
corsHandler = CorsHandler({
|
||||
allowedOrigins: [assertOrigin],
|
||||
allowedMethods: assertAllowedMethods,
|
||||
allowedHeaders: false,
|
||||
})
|
||||
ctx.method = 'OPTIONS'
|
||||
ctx.req.headers['origin'] = assertOrigin
|
||||
ctx.req.headers['access-control-request-method'] = 'GET'
|
||||
ctx.req.headers['access-control-request-headers'] = 'asdfasdfasdfsfad'
|
||||
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Origin'])
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Methods'])
|
||||
assert.notOk(ctx.headers['Access-Control-Allow-Headers'])
|
||||
|
||||
corsHandler(ctx)
|
||||
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Origin'], assertOrigin)
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Methods'], assertAllowedMethods)
|
||||
assert.strictEqual(ctx.headers['Access-Control-Allow-Headers'], undefined)
|
||||
assert.strictEqual(ctx.status, 204)
|
||||
})
|
||||
})
|
||||
|
||||
t.describe('#JsonHandler()', function() {
|
||||
let jsonHandler = JsonHandler()
|
||||
let ctx
|
||||
|
|
Loading…
Reference in a new issue