From 1da801ac64c4ff457b5a483b229a9fac7b5fe8cc Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Mon, 27 Sep 2021 19:27:08 +0200 Subject: [PATCH] wip --- packages/core/strapi/lib/Strapi.js | 2 + .../lib/core/app-configuration/index.js | 11 - .../strapi/lib/core/loaders/middlewares.js | 10 +- .../strapi/lib/middlewares/compression.js | 5 + .../lib/middlewares/error/defaults.json | 5 - .../strapi/lib/middlewares/error/index.js | 147 ---------- .../core/strapi/lib/middlewares/errors.js | 134 +++++++++ .../core/strapi/lib/middlewares/favicon.js | 17 ++ .../lib/middlewares/favicon/defaults.json | 7 - .../strapi/lib/middlewares/favicon/index.js | 31 --- .../strapi/lib/middlewares/gzip/defaults.json | 6 - .../core/strapi/lib/middlewares/gzip/index.js | 19 -- .../lib/middlewares/helmet/defaults.json | 18 -- packages/core/strapi/lib/middlewares/index.js | 262 ++++++++++-------- .../lib/middlewares/parser/defaults.json | 11 - .../strapi/lib/middlewares/parser/index.js | 75 ----- .../strapi/lib/middlewares/public/index.js | 6 + .../strapi/lib/middlewares/request-parser.js | 73 +++++ .../lib/middlewares/response-handlers.js | 16 ++ .../strapi/lib/middlewares/response-time.js | 12 + .../middlewares/responseTime/defaults.json | 5 - .../lib/middlewares/responseTime/index.js | 25 -- .../lib/middlewares/responses/defaults.json | 5 - .../strapi/lib/middlewares/responses/index.js | 19 -- .../lib/middlewares/router/defaults.json | 7 - .../{helmet/index.js => security.js} | 0 .../core/strapi/lib/services/server/index.js | 5 + .../server/register-routes.js} | 10 +- .../get-prefixed-dependencies.test.js | 25 -- .../lib/utils/get-prefixed-dependencies.js | 7 - 30 files changed, 429 insertions(+), 546 deletions(-) create mode 100644 packages/core/strapi/lib/middlewares/compression.js delete mode 100644 packages/core/strapi/lib/middlewares/error/defaults.json delete mode 100644 packages/core/strapi/lib/middlewares/error/index.js create mode 100644 packages/core/strapi/lib/middlewares/errors.js create mode 100644 packages/core/strapi/lib/middlewares/favicon.js delete mode 100644 packages/core/strapi/lib/middlewares/favicon/defaults.json delete mode 100644 packages/core/strapi/lib/middlewares/favicon/index.js delete mode 100644 packages/core/strapi/lib/middlewares/gzip/defaults.json delete mode 100644 packages/core/strapi/lib/middlewares/gzip/index.js delete mode 100644 packages/core/strapi/lib/middlewares/helmet/defaults.json delete mode 100644 packages/core/strapi/lib/middlewares/parser/defaults.json delete mode 100644 packages/core/strapi/lib/middlewares/parser/index.js create mode 100644 packages/core/strapi/lib/middlewares/request-parser.js create mode 100644 packages/core/strapi/lib/middlewares/response-handlers.js create mode 100644 packages/core/strapi/lib/middlewares/response-time.js delete mode 100644 packages/core/strapi/lib/middlewares/responseTime/defaults.json delete mode 100644 packages/core/strapi/lib/middlewares/responseTime/index.js delete mode 100644 packages/core/strapi/lib/middlewares/responses/defaults.json delete mode 100644 packages/core/strapi/lib/middlewares/responses/index.js delete mode 100644 packages/core/strapi/lib/middlewares/router/defaults.json rename packages/core/strapi/lib/middlewares/{helmet/index.js => security.js} (100%) rename packages/core/strapi/lib/{middlewares/router/index.js => services/server/register-routes.js} (92%) delete mode 100644 packages/core/strapi/lib/utils/__tests__/get-prefixed-dependencies.test.js delete mode 100644 packages/core/strapi/lib/utils/get-prefixed-dependencies.js diff --git a/packages/core/strapi/lib/Strapi.js b/packages/core/strapi/lib/Strapi.js index b9faa51298..25e40c8245 100644 --- a/packages/core/strapi/lib/Strapi.js +++ b/packages/core/strapi/lib/Strapi.js @@ -376,6 +376,8 @@ class Strapi { // Initialize middlewares. await initializeMiddlewares(this); + await this.server.initRouting(); + await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP); this.cron.start(); diff --git a/packages/core/strapi/lib/core/app-configuration/index.js b/packages/core/strapi/lib/core/app-configuration/index.js index 437ab19973..172db938f0 100644 --- a/packages/core/strapi/lib/core/app-configuration/index.js +++ b/packages/core/strapi/lib/core/app-configuration/index.js @@ -10,7 +10,6 @@ dotenv.config({ path: process.env.ENV_PATH }); process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -const getPrefixedDeps = require('../../utils/get-prefixed-dependencies'); const loadConfigDir = require('./config-loader'); const loadFunction = require('./load-functions'); @@ -31,15 +30,6 @@ const defaultConfig = { admin: { autoOpen: false }, }, admin: {}, - middleware: { - timeout: 1000, - load: { - before: ['responseTime', 'logger', 'cors', 'responses', 'gzip'], - order: [], - after: ['parser', 'router'], - }, - settings: {}, - }, }; module.exports = (dir, initialConfig = {}) => { @@ -63,7 +53,6 @@ module.exports = (dir, initialConfig = {}) => { strapi: strapiVersion, }, functions: loadFunction(path.join(configDir, 'functions')), - installedMiddlewares: getPrefixedDeps('@strapi/middleware', pkgJSON), }; const baseConfig = omit('plugins', loadConfigDir(configDir)); // plugin config will be loaded later diff --git a/packages/core/strapi/lib/core/loaders/middlewares.js b/packages/core/strapi/lib/core/loaders/middlewares.js index 830e1cd5ac..edf25859e7 100644 --- a/packages/core/strapi/lib/core/loaders/middlewares.js +++ b/packages/core/strapi/lib/core/loaders/middlewares.js @@ -9,18 +9,18 @@ const glob = require('../../load/glob'); * Load middlewares */ module.exports = async function(strapi) { - const installedMiddlewares = strapi.config.get('installedMiddlewares'); + // const installedMiddlewares = strapi.config.get('installedMiddlewares'); const appPath = strapi.config.get('appPath'); let middlewares = {}; - const loaders = createLoaders(strapi); + // const loaders = createLoaders(strapi); - await loaders.loadMiddlewareDependencies(installedMiddlewares, middlewares); + // await loaders.loadMiddlewareDependencies(installedMiddlewares, middlewares); // internal middlewares - await loaders.loadInternalMiddlewares(middlewares); + // await loaders.loadInternalMiddlewares(middlewares); // local middleware - await loaders.loadLocalMiddlewares(appPath, middlewares); + // await loaders.loadLocalMiddlewares(appPath, middlewares); return middlewares; }; diff --git a/packages/core/strapi/lib/middlewares/compression.js b/packages/core/strapi/lib/middlewares/compression.js new file mode 100644 index 0000000000..939f3c4198 --- /dev/null +++ b/packages/core/strapi/lib/middlewares/compression.js @@ -0,0 +1,5 @@ +'use strict'; + +const compress = require('koa-compress'); + +module.exports = (options = {}) => compress(options); diff --git a/packages/core/strapi/lib/middlewares/error/defaults.json b/packages/core/strapi/lib/middlewares/error/defaults.json deleted file mode 100644 index 54f3f00232..0000000000 --- a/packages/core/strapi/lib/middlewares/error/defaults.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "error": { - "enabled": true - } -} diff --git a/packages/core/strapi/lib/middlewares/error/index.js b/packages/core/strapi/lib/middlewares/error/index.js deleted file mode 100644 index 2889ca12cf..0000000000 --- a/packages/core/strapi/lib/middlewares/error/index.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; - -/** - * Boom hook - */ - -// Public node modules. -const _ = require('lodash'); -const Boom = require('@hapi/boom'); -const delegate = require('delegates'); - -const boomMethods = [ - 'badRequest', - 'unauthorized', - 'paymentRequired', - 'forbidden', - 'notFound', - 'methodNotAllowed', - 'notAcceptable', - 'proxyAuthRequired', - 'clientTimeout', - 'conflict', - 'resourceGone', - 'lengthRequired', - 'preconditionFailed', - 'entityTooLarge', - 'uriTooLong', - 'unsupportedMediaType', - 'rangeNotSatisfiable', - 'expectationFailed', - 'teapot', - 'badData', - 'locked', - 'failedDependency', - 'preconditionRequired', - 'tooManyRequests', - 'illegal', - 'badImplementation', - 'notImplemented', - 'badGateway', - 'serverUnavailable', - 'gatewayTimeout', -]; - -const formatBoomPayload = boomError => { - if (!Boom.isBoom(boomError)) { - boomError = Boom.boomify(boomError, { - statusCode: boomError.status || 500, - }); - } - - const { output } = boomError; - - if (output.statusCode < 500 && !_.isNil(boomError.data)) { - output.payload.data = boomError.data; - } - - return { status: output.statusCode, body: output.payload }; -}; - -module.exports = strapi => { - return { - /** - * Initialize the hook - */ - - initialize() { - this.delegator = delegate(strapi.server.app.context, 'response'); - this.createResponses(); - - strapi.errors = Boom; - strapi.server.use(async (ctx, next) => { - try { - // App logic. - await next(); - } catch (error) { - // emit error if configured - if (strapi.config.get('server.emitErrors', false)) { - strapi.server.app.emit('error', error, ctx); - } - - // Log error. - - const { status, body } = formatBoomPayload(error); - - if (status >= 500) { - strapi.log.error(error); - } - - ctx.body = body; - ctx.status = status; - } - }); - - strapi.server.use(async (ctx, next) => { - await next(); - // Empty body is considered as `notFound` response. - if (_.isNil(ctx.body) && (_.isNil(ctx.status) || ctx.status === 404)) { - ctx.notFound(); - } - }); - }, - - // Custom function to avoid ctx.body repeat - createResponses() { - boomMethods.forEach(method => { - strapi.server.app.response[method] = function(msg, ...rest) { - const boomError = Boom[method](msg, ...rest) || {}; - - const { status, body } = formatBoomPayload(boomError); - - // keep retro-compatibility for old error formats - body.message = msg || body.data || body.message; - - this.body = body; - this.status = status; - }; - - this.delegator.method(method); - }); - - strapi.server.app.response.send = function(data, status = 200) { - this.status = status; - this.body = data; - }; - - strapi.server.app.response.created = function(data) { - this.status = 201; - this.body = data; - }; - - strapi.server.app.response.deleted = function(data) { - if (_.isNil(data)) { - this.status = 204; - } else { - this.status = 200; - this.body = data; - } - }; - - this.delegator - .method('send') - .method('created') - .method('deleted'); - }, - }; -}; diff --git a/packages/core/strapi/lib/middlewares/errors.js b/packages/core/strapi/lib/middlewares/errors.js new file mode 100644 index 0000000000..394eac5aa6 --- /dev/null +++ b/packages/core/strapi/lib/middlewares/errors.js @@ -0,0 +1,134 @@ +'use strict'; + +/** + * Boom hook + */ + +// Public node modules. +const _ = require('lodash'); +const Boom = require('@hapi/boom'); +const delegate = require('delegates'); + +const boomMethods = [ + 'badRequest', + 'unauthorized', + 'paymentRequired', + 'forbidden', + 'notFound', + 'methodNotAllowed', + 'notAcceptable', + 'proxyAuthRequired', + 'clientTimeout', + 'conflict', + 'resourceGone', + 'lengthRequired', + 'preconditionFailed', + 'entityTooLarge', + 'uriTooLong', + 'unsupportedMediaType', + 'rangeNotSatisfiable', + 'expectationFailed', + 'teapot', + 'badData', + 'locked', + 'failedDependency', + 'preconditionRequired', + 'tooManyRequests', + 'illegal', + 'badImplementation', + 'notImplemented', + 'badGateway', + 'serverUnavailable', + 'gatewayTimeout', +]; + +const formatBoomPayload = boomError => { + if (!Boom.isBoom(boomError)) { + boomError = Boom.boomify(boomError, { + statusCode: boomError.status || 500, + }); + } + + const { output } = boomError; + + if (output.statusCode < 500 && !_.isNil(boomError.data)) { + output.payload.data = boomError.data; + } + + return { status: output.statusCode, body: output.payload }; +}; + +const createResponseUtils = () => { + const delegator = delegate(strapi.server.app.context, 'response'); + + boomMethods.forEach(method => { + strapi.server.app.response[method] = function(msg, ...rest) { + const boomError = Boom[method](msg, ...rest) || {}; + + const { status, body } = formatBoomPayload(boomError); + + // keep retro-compatibility for old error formats + body.message = msg || body.data || body.message; + + this.body = body; + this.status = status; + }; + + delegator.method(method); + }); + + strapi.server.app.response.send = function(data, status = 200) { + this.status = status; + this.body = data; + }; + + strapi.server.app.response.created = function(data) { + this.status = 201; + this.body = data; + }; + + strapi.server.app.response.deleted = function(data) { + if (_.isNil(data)) { + this.status = 204; + } else { + this.status = 200; + this.body = data; + } + }; + + delegator + .method('send') + .method('created') + .method('deleted'); +}; + +// TODO: inject strapi +module.exports = () => { + createResponseUtils(); + strapi.errors = Boom; + + return async (ctx, next) => { + try { + // App logic. + await next(); + + if (_.isNil(ctx.body) && (_.isNil(ctx.status) || ctx.status === 404)) { + ctx.notFound(); + } + } catch (error) { + // emit error if configured + if (strapi.config.get('server.emitErrors', false)) { + strapi.server.app.emit('error', error, ctx); + } + + const { status, body } = formatBoomPayload(error); + + if (status >= 500) { + strapi.log.error(error); + } + + ctx.body = body; + ctx.status = status; + } + }; +}; diff --git a/packages/core/strapi/lib/middlewares/favicon.js b/packages/core/strapi/lib/middlewares/favicon.js new file mode 100644 index 0000000000..744f4ae1f5 --- /dev/null +++ b/packages/core/strapi/lib/middlewares/favicon.js @@ -0,0 +1,17 @@ +'use strict'; + +const { resolve } = require('path'); +const { defaultsDeep } = require('lodash'); +const favicon = require('koa-favicon'); + +const defaults = { + path: 'favicon.ico', + maxAge: 86400000, +}; + +// TODO: inject strapi +module.exports = options => { + const { maxAge, path: faviconPath } = defaultsDeep(defaults, options); + + return favicon(resolve(strapi.dirs.root, faviconPath), { maxAge }); +}; diff --git a/packages/core/strapi/lib/middlewares/favicon/defaults.json b/packages/core/strapi/lib/middlewares/favicon/defaults.json deleted file mode 100644 index 33c7a6da94..0000000000 --- a/packages/core/strapi/lib/middlewares/favicon/defaults.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "favicon": { - "enabled": true, - "path": "favicon.ico", - "maxAge": 86400000 - } -} diff --git a/packages/core/strapi/lib/middlewares/favicon/index.js b/packages/core/strapi/lib/middlewares/favicon/index.js deleted file mode 100644 index fd55a6550e..0000000000 --- a/packages/core/strapi/lib/middlewares/favicon/index.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Node.js core. -const { resolve } = require('path'); -const favicon = require('koa-favicon'); - -/** - * Favicon hook - */ - -module.exports = strapi => { - return { - /** - * Initialize the hook - */ - - initialize() { - const { maxAge, path: faviconPath } = strapi.config.middleware.settings.favicon; - - strapi.server.use( - favicon(resolve(strapi.dirs.root, faviconPath), { - maxAge, - }) - ); - }, - }; -}; diff --git a/packages/core/strapi/lib/middlewares/gzip/defaults.json b/packages/core/strapi/lib/middlewares/gzip/defaults.json deleted file mode 100644 index 448546ea77..0000000000 --- a/packages/core/strapi/lib/middlewares/gzip/defaults.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "gzip": { - "enabled": false, - "options": {} - } -} diff --git a/packages/core/strapi/lib/middlewares/gzip/index.js b/packages/core/strapi/lib/middlewares/gzip/index.js deleted file mode 100644 index 479bba7523..0000000000 --- a/packages/core/strapi/lib/middlewares/gzip/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -/** - * Gzip hook - */ -const compress = require('koa-compress'); - -module.exports = strapi => { - return { - /** - * Initialize the hook - */ - - initialize() { - const { options = {} } = strapi.config.middleware.settings.gzip; - strapi.server.use(compress(options)); - }, - }; -}; diff --git a/packages/core/strapi/lib/middlewares/helmet/defaults.json b/packages/core/strapi/lib/middlewares/helmet/defaults.json deleted file mode 100644 index 1d87c53323..0000000000 --- a/packages/core/strapi/lib/middlewares/helmet/defaults.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "helmet": { - "enabled": true, - "crossOriginEmbedderPolicy": false, - "crossOriginOpenerPolicy": false, - "crossOriginResourcePolicy": false, - "originAgentCluster": false, - "contentSecurityPolicy": false, - "xssFilter": false, - "hsts": { - "maxAge": 31536000, - "includeSubDomains": true - }, - "frameguard": { - "action": "sameorigin" - } - } -} diff --git a/packages/core/strapi/lib/middlewares/index.js b/packages/core/strapi/lib/middlewares/index.js index 579e86a00c..c1541e6b3c 100644 --- a/packages/core/strapi/lib/middlewares/index.js +++ b/packages/core/strapi/lib/middlewares/index.js @@ -1,120 +1,156 @@ 'use strict'; -const { uniq, difference, get, isUndefined, merge } = require('lodash'); +const compression = require('./compression'); +const cors = require('./cors'); +const errors = require('./errors'); +const favicon = require('./favicon'); +const ip = require('./ip'); +const logger = require('./logger'); +const poweredBy = require('./powered-by'); +const requestParser = require('./request-parser'); +const responseTime = require('./response-time'); +const responseHandlers = require('./response-handlers'); +const security = require('./security'); +// session: require('./session'), +const publicStatic = require('./public'); -const requiredMiddlewares = [ - 'auth', - 'responses', - 'router', - 'logger', - 'error', - 'cors', - 'cron', - 'xframe', - 'xss', - 'public', - 'favicon', +const INTERNAL_MIDDLEWARES = [ + errors, + ip, + security, + cors, + responseTime, + poweredBy, + logger, + compression, + responseHandlers, + requestParser, + favicon, + publicStatic, ]; -module.exports = async function(strapi) { - /** Utils */ - const middlewareConfig = strapi.config.middleware; +module.exports = async strapi => { + for (const middlewareFactory of INTERNAL_MIDDLEWARES) { + // const config = strapi.config.get(`middlwares`); + const middleware = middlewareFactory({}); - // check if a middleware exists - const middlewareExists = key => { - return !isUndefined(strapi.middleware[key]); - }; - - // check if a middleware is enabled - const middlewareEnabled = key => { - return ( - requiredMiddlewares.includes(key) || - get(middlewareConfig, ['settings', key, 'enabled'], false) === true - ); - }; - - // list of enabled middlewares - const enabledMiddlewares = Object.keys(strapi.middleware).filter(middlewareEnabled); - - // Method to initialize middlewares and emit an event. - const initialize = middlewareKey => { - if (strapi.middleware[middlewareKey].loaded === true) return; - - const module = strapi.middleware[middlewareKey].load; - - return new Promise((resolve, reject) => { - const timeout = setTimeout( - () => reject(`(middleware: ${middlewareKey}) is taking too long to load.`), - middlewareConfig.timeout || 1000 - ); - strapi.middleware[middlewareKey] = merge(strapi.middleware[middlewareKey], module); - - Promise.resolve() - .then(() => module.initialize(strapi)) - .then(() => { - clearTimeout(timeout); - strapi.middleware[middlewareKey].loaded = true; - resolve(); - }) - .catch(err => { - clearTimeout(timeout); - - if (err) { - return reject(err); - } - }); - }); - }; - - /** - * Run init functions - */ - - // Run beforeInitialize of every middleware - await Promise.all( - enabledMiddlewares.map(key => { - const { beforeInitialize } = strapi.middleware[key].load; - if (typeof beforeInitialize === 'function') { - return beforeInitialize(strapi); - } - }) - ); - - // run the initialization of an array of middlewares sequentially - const initMiddlewaresSeq = async middlewareArr => { - for (let key of uniq(middlewareArr)) { - await initialize(key); - } - }; - - const middlewaresBefore = get(middlewareConfig, 'load.before', []) - .filter(middlewareExists) - .filter(middlewareEnabled); - - const middlewaresAfter = get(middlewareConfig, 'load.after', []) - .filter(middlewareExists) - .filter(middlewareEnabled); - - const middlewaresOrder = get(middlewareConfig, 'load.order', []) - .filter(middlewareExists) - .filter(middlewareEnabled); - - const unspecifiedMiddlewares = difference( - enabledMiddlewares, - middlewaresBefore, - middlewaresOrder, - middlewaresAfter - ); - - // before - await initMiddlewaresSeq(middlewaresBefore); - - // ordered // rest of middlewares - await Promise.all([ - initMiddlewaresSeq(middlewaresOrder), - Promise.all(unspecifiedMiddlewares.map(initialize)), - ]); - - // after - await initMiddlewaresSeq(middlewaresAfter); + strapi.server.use(middleware); + } }; + +// const requiredMiddlewares = [ +// 'auth', +// 'responses', +// 'router', +// 'logger', +// 'error', +// 'cors', +// 'cron', +// 'xframe', +// 'xss', +// 'public', +// 'favicon', +// ]; + +// module.exports = async function(strapi) { +// /** Utils */ +// const middlewareConfig = strapi.config.middleware; + +// // check if a middleware exists +// const middlewareExists = key => { +// return !isUndefined(strapi.middleware[key]); +// }; + +// // check if a middleware is enabled +// const middlewareEnabled = key => { +// return ( +// requiredMiddlewares.includes(key) || +// get(middlewareConfig, ['settings', key, 'enabled'], false) === true +// ); +// }; + +// // list of enabled middlewares +// const enabledMiddlewares = Object.keys(strapi.middleware).filter(middlewareEnabled); + +// // Method to initialize middlewares and emit an event. +// const initialize = middlewareKey => { +// if (strapi.middleware[middlewareKey].loaded === true) return; + +// const module = strapi.middleware[middlewareKey].load; + +// return new Promise((resolve, reject) => { +// const timeout = setTimeout( +// () => reject(`(middleware: ${middlewareKey}) is taking too long to load.`), +// middlewareConfig.timeout || 1000 +// ); +// strapi.middleware[middlewareKey] = merge(strapi.middleware[middlewareKey], module); + +// Promise.resolve() +// .then(() => module.initialize(strapi)) +// .then(() => { +// clearTimeout(timeout); +// strapi.middleware[middlewareKey].loaded = true; +// resolve(); +// }) +// .catch(err => { +// clearTimeout(timeout); + +// if (err) { +// return reject(err); +// } +// }); +// }); +// }; + +// /** +// * Run init functions +// */ + +// // Run beforeInitialize of every middleware +// await Promise.all( +// enabledMiddlewares.map(key => { +// const { beforeInitialize } = strapi.middleware[key].load; +// if (typeof beforeInitialize === 'function') { +// return beforeInitialize(strapi); +// } +// }) +// ); + +// // run the initialization of an array of middlewares sequentially +// const initMiddlewaresSeq = async middlewareArr => { +// for (let key of uniq(middlewareArr)) { +// await initialize(key); +// } +// }; + +// const middlewaresBefore = get(middlewareConfig, 'load.before', []) +// .filter(middlewareExists) +// .filter(middlewareEnabled); + +// const middlewaresAfter = get(middlewareConfig, 'load.after', []) +// .filter(middlewareExists) +// .filter(middlewareEnabled); + +// const middlewaresOrder = get(middlewareConfig, 'load.order', []) +// .filter(middlewareExists) +// .filter(middlewareEnabled); + +// const unspecifiedMiddlewares = difference( +// enabledMiddlewares, +// middlewaresBefore, +// middlewaresOrder, +// middlewaresAfter +// ); + +// // before +// await initMiddlewaresSeq(middlewaresBefore); + +// // ordered // rest of middlewares +// await Promise.all([ +// initMiddlewaresSeq(middlewaresOrder), +// Promise.all(unspecifiedMiddlewares.map(initialize)), +// ]); + +// // after +// await initMiddlewaresSeq(middlewaresAfter); +// }; diff --git a/packages/core/strapi/lib/middlewares/parser/defaults.json b/packages/core/strapi/lib/middlewares/parser/defaults.json deleted file mode 100644 index d31e0c08c3..0000000000 --- a/packages/core/strapi/lib/middlewares/parser/defaults.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parser": { - "enabled": true, - "multipart": true, - "queryStringParser": { - "strictNullHandling": true, - "arrayLimit": 100, - "depth": 20 - } - } -} diff --git a/packages/core/strapi/lib/middlewares/parser/index.js b/packages/core/strapi/lib/middlewares/parser/index.js deleted file mode 100644 index b1a18526ee..0000000000 --- a/packages/core/strapi/lib/middlewares/parser/index.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict'; - -const body = require('koa-body'); -const qs = require('qs'); -const { omit } = require('lodash'); - -/** - * Body parser hook - */ -const addQsParser = (app, settings) => { - Object.defineProperty(app.request, 'query', { - configurable: false, - enumerable: true, - /* - * Get parsed query-string. - */ - get() { - const qstr = this.querystring; - const cache = (this._querycache = this._querycache || {}); - return cache[qstr] || (cache[qstr] = qs.parse(qstr, settings)); - }, - - /* - * Set query-string as an object. - */ - set(obj) { - this.querystring = qs.stringify(obj); - }, - }); - - return app; -}; - -module.exports = strapi => { - return { - /** - * Initialize the hook - */ - initialize() { - strapi.server.use(async (ctx, next) => { - // disable for graphql - // TODO: find a better way later - if (ctx.url === '/graphql') { - return next(); - } - - try { - const res = await body({ - patchKoa: true, - ...omit(strapi.config.middleware.settings.parser, 'queryStringParser'), - })(ctx, next); - return res; - } catch (e) { - if ((e || {}).message && e.message.includes('maxFileSize exceeded')) { - throw strapi.errors.entityTooLarge('FileTooBig', { - errors: [ - { - id: 'Upload.status.sizeLimit', - message: `file is bigger than the limit size!`, - }, - ], - }); - } - - throw e; - } - }); - - addQsParser( - strapi.server.app, - strapi.config.get('middleware.settings.parser.queryStringParser') - ); - }, - }; -}; diff --git a/packages/core/strapi/lib/middlewares/public/index.js b/packages/core/strapi/lib/middlewares/public/index.js index 3936fa27fb..013fc5d6f7 100644 --- a/packages/core/strapi/lib/middlewares/public/index.js +++ b/packages/core/strapi/lib/middlewares/public/index.js @@ -18,6 +18,12 @@ const serveStatic = require('./serve-static'); */ module.exports = strapi => { + + + return async (ctx, next) => { + return next(); + } + return { /** * Initialize the hook diff --git a/packages/core/strapi/lib/middlewares/request-parser.js b/packages/core/strapi/lib/middlewares/request-parser.js new file mode 100644 index 0000000000..5756cbd08f --- /dev/null +++ b/packages/core/strapi/lib/middlewares/request-parser.js @@ -0,0 +1,73 @@ +'use strict'; + +const { defaultsDeep } = require('lodash/fp'); +const body = require('koa-body'); +const qs = require('qs'); + +const defaults = { + multipart: true, + queryStringParser: { + strictNullHandling: true, + arrayLimit: 100, + depth: 20, + }, +}; + +/** + * Body parser hook + */ +const addQsParser = (app, settings) => { + Object.defineProperty(app.request, 'query', { + configurable: false, + enumerable: true, + /* + * Get parsed query-string. + */ + get() { + const qstr = this.querystring; + const cache = (this._querycache = this._querycache || {}); + return cache[qstr] || (cache[qstr] = qs.parse(qstr, settings)); + }, + + /* + * Set query-string as an object. + */ + set(obj) { + this.querystring = qs.stringify(obj); + }, + }); + + return app; +}; + +// TODO: inject strapi +module.exports = options => { + const { queryStringParser, ...bodyOptions } = defaultsDeep(defaults, options); + + addQsParser(strapi.server.app, queryStringParser); + + return async (ctx, next) => { + // disable for graphql + // TODO: find a better way later + if (ctx.url === '/graphql') { + return next(); + } + + try { + return body({ patchKoa: true, ...bodyOptions })(ctx, next); + } catch (e) { + if ((e || {}).message && e.message.includes('maxFileSize exceeded')) { + throw strapi.errors.entityTooLarge('FileTooBig', { + errors: [ + { + id: 'parser.file.status.sizeLimit', + message: `file is bigger than the limit size!`, + }, + ], + }); + } + + throw e; + } + }; +}; diff --git a/packages/core/strapi/lib/middlewares/response-handlers.js b/packages/core/strapi/lib/middlewares/response-handlers.js new file mode 100644 index 0000000000..8be3f0c408 --- /dev/null +++ b/packages/core/strapi/lib/middlewares/response-handlers.js @@ -0,0 +1,16 @@ +'use strict'; + +const { prop, isFunction } = require('lodash/fp'); + +module.exports = (options = {}) => { + return async (ctx, next) => { + await next(); + + const status = ctx.status; + const handler = prop(`handlers.${status}`, options); + + if (isFunction(handler)) { + await handler(ctx); + } + }; +}; diff --git a/packages/core/strapi/lib/middlewares/response-time.js b/packages/core/strapi/lib/middlewares/response-time.js new file mode 100644 index 0000000000..89c56f7b14 --- /dev/null +++ b/packages/core/strapi/lib/middlewares/response-time.js @@ -0,0 +1,12 @@ +'use strict'; + +module.exports = () => { + return async (ctx, next) => { + const start = Date.now(); + + await next(); + + const delta = Math.ceil(Date.now() - start); + ctx.set('X-Response-Time', delta + 'ms'); + }; +}; diff --git a/packages/core/strapi/lib/middlewares/responseTime/defaults.json b/packages/core/strapi/lib/middlewares/responseTime/defaults.json deleted file mode 100644 index b5c12d577a..0000000000 --- a/packages/core/strapi/lib/middlewares/responseTime/defaults.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "responseTime": { - "enabled": true - } -} diff --git a/packages/core/strapi/lib/middlewares/responseTime/index.js b/packages/core/strapi/lib/middlewares/responseTime/index.js deleted file mode 100644 index b019a2feaa..0000000000 --- a/packages/core/strapi/lib/middlewares/responseTime/index.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -/** - * X-Response-Time hook - */ - -module.exports = strapi => { - return { - /** - * Initialize the hook - */ - - initialize() { - strapi.server.use(async (ctx, next) => { - const start = Date.now(); - - await next(); - - const delta = Math.ceil(Date.now() - start); - - ctx.set('X-Response-Time', delta + 'ms'); // eslint-disable-line prefer-template - }); - }, - }; -}; diff --git a/packages/core/strapi/lib/middlewares/responses/defaults.json b/packages/core/strapi/lib/middlewares/responses/defaults.json deleted file mode 100644 index b2dae41dd4..0000000000 --- a/packages/core/strapi/lib/middlewares/responses/defaults.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "responses": { - "enabled": true - } -} diff --git a/packages/core/strapi/lib/middlewares/responses/index.js b/packages/core/strapi/lib/middlewares/responses/index.js deleted file mode 100644 index 4ab792ce02..0000000000 --- a/packages/core/strapi/lib/middlewares/responses/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -const _ = require('lodash'); - -module.exports = strapi => { - return { - initialize() { - strapi.server.use(async (ctx, next) => { - await next(); - - const status = ctx.status; - const responseFn = strapi.config.get(`middleware.settings.responses.handlers.${status}`); - if (_.isFunction(responseFn)) { - await responseFn(ctx); - } - }); - }, - }; -}; diff --git a/packages/core/strapi/lib/middlewares/router/defaults.json b/packages/core/strapi/lib/middlewares/router/defaults.json deleted file mode 100644 index 9bc1c03300..0000000000 --- a/packages/core/strapi/lib/middlewares/router/defaults.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "router": { - "enabled": true, - "prefix": "", - "routes": {} - } -} diff --git a/packages/core/strapi/lib/middlewares/helmet/index.js b/packages/core/strapi/lib/middlewares/security.js similarity index 100% rename from packages/core/strapi/lib/middlewares/helmet/index.js rename to packages/core/strapi/lib/middlewares/security.js diff --git a/packages/core/strapi/lib/services/server/index.js b/packages/core/strapi/lib/services/server/index.js index 9d549f28d8..62db30ec9f 100644 --- a/packages/core/strapi/lib/services/server/index.js +++ b/packages/core/strapi/lib/services/server/index.js @@ -7,6 +7,7 @@ const { createHTTPServer } = require('./http-server'); const { createRouteManager } = require('./routing'); const { createAdminAPI } = require('./admin-api'); const { createContentAPI } = require('./content-api'); +const registerAllRoutes = require('./register-routes'); const healthCheck = async ctx => { ctx.set('strapi', 'You are so French!'); @@ -89,6 +90,10 @@ const createServer = strapi => { return this; }, + initRouting() { + registerAllRoutes(strapi); + }, + listen(...args) { if (!state.mounted) { this.mount(); diff --git a/packages/core/strapi/lib/middlewares/router/index.js b/packages/core/strapi/lib/services/server/register-routes.js similarity index 92% rename from packages/core/strapi/lib/middlewares/router/index.js rename to packages/core/strapi/lib/services/server/register-routes.js index a97684c182..7ab6064c92 100644 --- a/packages/core/strapi/lib/middlewares/router/index.js +++ b/packages/core/strapi/lib/services/server/register-routes.js @@ -19,7 +19,7 @@ const createRouteScopeGenerator = namespace => route => { } }; -module.exports = strapi => { +module.exports = (server, strapi) => { const registerAdminRoutes = () => { const generateRouteScope = createRouteScopeGenerator(`admin::`); @@ -28,7 +28,7 @@ module.exports = strapi => { route.info = { pluginName: 'admin' }; }); - strapi.server.routes({ + server.routes({ type: 'admin', prefix: '/admin', routes: strapi.admin.routes, @@ -47,7 +47,7 @@ module.exports = strapi => { route.info = { pluginName }; }); - strapi.server.routes({ + server.routes({ type: 'admin', prefix: `/${pluginName}`, routes: plugin.routes, @@ -61,7 +61,7 @@ module.exports = strapi => { route.info = { pluginName }; }); - strapi.server.routes(router); + server.routes(router); }); } } @@ -82,7 +82,7 @@ module.exports = strapi => { route.info = { apiName }; }); - return strapi.server.routes(router); + return server.routes(router); }); } }; diff --git a/packages/core/strapi/lib/utils/__tests__/get-prefixed-dependencies.test.js b/packages/core/strapi/lib/utils/__tests__/get-prefixed-dependencies.test.js deleted file mode 100644 index 206d4dc1ef..0000000000 --- a/packages/core/strapi/lib/utils/__tests__/get-prefixed-dependencies.test.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -const getPrefixedDeps = require('../get-prefixed-dependencies'); - -describe('getPrefixedDeps', () => { - test('Returns a list of the dependencies and removes the prefix', () => { - expect( - getPrefixedDeps('test-prefix', { - dependencies: { - 'test-prefix-packagename': '1', - }, - }) - ).toEqual(['packagename']); - }); - - test('Ignores exact names', () => { - expect( - getPrefixedDeps('test-prefix', { - dependencies: { - 'test-prefix': '1', - }, - }) - ).toEqual([]); - }); -}); diff --git a/packages/core/strapi/lib/utils/get-prefixed-dependencies.js b/packages/core/strapi/lib/utils/get-prefixed-dependencies.js deleted file mode 100644 index 185b812946..0000000000 --- a/packages/core/strapi/lib/utils/get-prefixed-dependencies.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -module.exports = (prefix, pkgJSON) => { - return Object.keys(pkgJSON.dependencies) - .filter(d => d.startsWith(prefix) && d.length > prefix.length) - .map(pkgName => pkgName.substring(prefix.length + 1)); -};