mirror of
https://github.com/strapi/strapi.git
synced 2025-09-10 17:17:19 +00:00
wip
This commit is contained in:
parent
b63c330c58
commit
1da801ac64
@ -376,6 +376,8 @@ class Strapi {
|
|||||||
// Initialize middlewares.
|
// Initialize middlewares.
|
||||||
await initializeMiddlewares(this);
|
await initializeMiddlewares(this);
|
||||||
|
|
||||||
|
await this.server.initRouting();
|
||||||
|
|
||||||
await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP);
|
await this.runLifecyclesFunctions(LIFECYCLES.BOOTSTRAP);
|
||||||
|
|
||||||
this.cron.start();
|
this.cron.start();
|
||||||
|
@ -10,7 +10,6 @@ dotenv.config({ path: process.env.ENV_PATH });
|
|||||||
|
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
const getPrefixedDeps = require('../../utils/get-prefixed-dependencies');
|
|
||||||
const loadConfigDir = require('./config-loader');
|
const loadConfigDir = require('./config-loader');
|
||||||
const loadFunction = require('./load-functions');
|
const loadFunction = require('./load-functions');
|
||||||
|
|
||||||
@ -31,15 +30,6 @@ const defaultConfig = {
|
|||||||
admin: { autoOpen: false },
|
admin: { autoOpen: false },
|
||||||
},
|
},
|
||||||
admin: {},
|
admin: {},
|
||||||
middleware: {
|
|
||||||
timeout: 1000,
|
|
||||||
load: {
|
|
||||||
before: ['responseTime', 'logger', 'cors', 'responses', 'gzip'],
|
|
||||||
order: [],
|
|
||||||
after: ['parser', 'router'],
|
|
||||||
},
|
|
||||||
settings: {},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = (dir, initialConfig = {}) => {
|
module.exports = (dir, initialConfig = {}) => {
|
||||||
@ -63,7 +53,6 @@ module.exports = (dir, initialConfig = {}) => {
|
|||||||
strapi: strapiVersion,
|
strapi: strapiVersion,
|
||||||
},
|
},
|
||||||
functions: loadFunction(path.join(configDir, 'functions')),
|
functions: loadFunction(path.join(configDir, 'functions')),
|
||||||
installedMiddlewares: getPrefixedDeps('@strapi/middleware', pkgJSON),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseConfig = omit('plugins', loadConfigDir(configDir)); // plugin config will be loaded later
|
const baseConfig = omit('plugins', loadConfigDir(configDir)); // plugin config will be loaded later
|
||||||
|
@ -9,18 +9,18 @@ const glob = require('../../load/glob');
|
|||||||
* Load middlewares
|
* Load middlewares
|
||||||
*/
|
*/
|
||||||
module.exports = async function(strapi) {
|
module.exports = async function(strapi) {
|
||||||
const installedMiddlewares = strapi.config.get('installedMiddlewares');
|
// const installedMiddlewares = strapi.config.get('installedMiddlewares');
|
||||||
const appPath = strapi.config.get('appPath');
|
const appPath = strapi.config.get('appPath');
|
||||||
|
|
||||||
let middlewares = {};
|
let middlewares = {};
|
||||||
|
|
||||||
const loaders = createLoaders(strapi);
|
// const loaders = createLoaders(strapi);
|
||||||
|
|
||||||
await loaders.loadMiddlewareDependencies(installedMiddlewares, middlewares);
|
// await loaders.loadMiddlewareDependencies(installedMiddlewares, middlewares);
|
||||||
// internal middlewares
|
// internal middlewares
|
||||||
await loaders.loadInternalMiddlewares(middlewares);
|
// await loaders.loadInternalMiddlewares(middlewares);
|
||||||
// local middleware
|
// local middleware
|
||||||
await loaders.loadLocalMiddlewares(appPath, middlewares);
|
// await loaders.loadLocalMiddlewares(appPath, middlewares);
|
||||||
|
|
||||||
return middlewares;
|
return middlewares;
|
||||||
};
|
};
|
||||||
|
5
packages/core/strapi/lib/middlewares/compression.js
Normal file
5
packages/core/strapi/lib/middlewares/compression.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const compress = require('koa-compress');
|
||||||
|
|
||||||
|
module.exports = (options = {}) => compress(options);
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"error": {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -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');
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
134
packages/core/strapi/lib/middlewares/errors.js
Normal file
134
packages/core/strapi/lib/middlewares/errors.js
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
17
packages/core/strapi/lib/middlewares/favicon.js
Normal file
17
packages/core/strapi/lib/middlewares/favicon.js
Normal file
@ -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 });
|
||||||
|
};
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"favicon": {
|
|
||||||
"enabled": true,
|
|
||||||
"path": "favicon.ico",
|
|
||||||
"maxAge": 86400000
|
|
||||||
}
|
|
||||||
}
|
|
@ -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,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"gzip": {
|
|
||||||
"enabled": false,
|
|
||||||
"options": {}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,120 +1,156 @@
|
|||||||
'use strict';
|
'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 = [
|
const INTERNAL_MIDDLEWARES = [
|
||||||
'auth',
|
errors,
|
||||||
'responses',
|
ip,
|
||||||
'router',
|
security,
|
||||||
'logger',
|
cors,
|
||||||
'error',
|
responseTime,
|
||||||
'cors',
|
poweredBy,
|
||||||
'cron',
|
logger,
|
||||||
'xframe',
|
compression,
|
||||||
'xss',
|
responseHandlers,
|
||||||
'public',
|
requestParser,
|
||||||
'favicon',
|
favicon,
|
||||||
|
publicStatic,
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = async function(strapi) {
|
module.exports = async strapi => {
|
||||||
/** Utils */
|
for (const middlewareFactory of INTERNAL_MIDDLEWARES) {
|
||||||
const middlewareConfig = strapi.config.middleware;
|
// const config = strapi.config.get(`middlwares`);
|
||||||
|
const middleware = middlewareFactory({});
|
||||||
|
|
||||||
// check if a middleware exists
|
strapi.server.use(middleware);
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// };
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"parser": {
|
|
||||||
"enabled": true,
|
|
||||||
"multipart": true,
|
|
||||||
"queryStringParser": {
|
|
||||||
"strictNullHandling": true,
|
|
||||||
"arrayLimit": 100,
|
|
||||||
"depth": 20
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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')
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@ -18,6 +18,12 @@ const serveStatic = require('./serve-static');
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = strapi => {
|
module.exports = strapi => {
|
||||||
|
|
||||||
|
|
||||||
|
return async (ctx, next) => {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
* Initialize the hook
|
* Initialize the hook
|
||||||
|
73
packages/core/strapi/lib/middlewares/request-parser.js
Normal file
73
packages/core/strapi/lib/middlewares/request-parser.js
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
16
packages/core/strapi/lib/middlewares/response-handlers.js
Normal file
16
packages/core/strapi/lib/middlewares/response-handlers.js
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
12
packages/core/strapi/lib/middlewares/response-time.js
Normal file
12
packages/core/strapi/lib/middlewares/response-time.js
Normal file
@ -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');
|
||||||
|
};
|
||||||
|
};
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"responseTime": {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"responses": {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"router": {
|
|
||||||
"enabled": true,
|
|
||||||
"prefix": "",
|
|
||||||
"routes": {}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,6 +7,7 @@ const { createHTTPServer } = require('./http-server');
|
|||||||
const { createRouteManager } = require('./routing');
|
const { createRouteManager } = require('./routing');
|
||||||
const { createAdminAPI } = require('./admin-api');
|
const { createAdminAPI } = require('./admin-api');
|
||||||
const { createContentAPI } = require('./content-api');
|
const { createContentAPI } = require('./content-api');
|
||||||
|
const registerAllRoutes = require('./register-routes');
|
||||||
|
|
||||||
const healthCheck = async ctx => {
|
const healthCheck = async ctx => {
|
||||||
ctx.set('strapi', 'You are so French!');
|
ctx.set('strapi', 'You are so French!');
|
||||||
@ -89,6 +90,10 @@ const createServer = strapi => {
|
|||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initRouting() {
|
||||||
|
registerAllRoutes(strapi);
|
||||||
|
},
|
||||||
|
|
||||||
listen(...args) {
|
listen(...args) {
|
||||||
if (!state.mounted) {
|
if (!state.mounted) {
|
||||||
this.mount();
|
this.mount();
|
||||||
|
@ -19,7 +19,7 @@ const createRouteScopeGenerator = namespace => route => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = strapi => {
|
module.exports = (server, strapi) => {
|
||||||
const registerAdminRoutes = () => {
|
const registerAdminRoutes = () => {
|
||||||
const generateRouteScope = createRouteScopeGenerator(`admin::`);
|
const generateRouteScope = createRouteScopeGenerator(`admin::`);
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ module.exports = strapi => {
|
|||||||
route.info = { pluginName: 'admin' };
|
route.info = { pluginName: 'admin' };
|
||||||
});
|
});
|
||||||
|
|
||||||
strapi.server.routes({
|
server.routes({
|
||||||
type: 'admin',
|
type: 'admin',
|
||||||
prefix: '/admin',
|
prefix: '/admin',
|
||||||
routes: strapi.admin.routes,
|
routes: strapi.admin.routes,
|
||||||
@ -47,7 +47,7 @@ module.exports = strapi => {
|
|||||||
route.info = { pluginName };
|
route.info = { pluginName };
|
||||||
});
|
});
|
||||||
|
|
||||||
strapi.server.routes({
|
server.routes({
|
||||||
type: 'admin',
|
type: 'admin',
|
||||||
prefix: `/${pluginName}`,
|
prefix: `/${pluginName}`,
|
||||||
routes: plugin.routes,
|
routes: plugin.routes,
|
||||||
@ -61,7 +61,7 @@ module.exports = strapi => {
|
|||||||
route.info = { pluginName };
|
route.info = { pluginName };
|
||||||
});
|
});
|
||||||
|
|
||||||
strapi.server.routes(router);
|
server.routes(router);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ module.exports = strapi => {
|
|||||||
route.info = { apiName };
|
route.info = { apiName };
|
||||||
});
|
});
|
||||||
|
|
||||||
return strapi.server.routes(router);
|
return server.routes(router);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -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([]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -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));
|
|
||||||
};
|
|
Loading…
x
Reference in New Issue
Block a user