mirror of
https://github.com/strapi/strapi.git
synced 2026-01-08 05:04:10 +00:00
Move server into services
This commit is contained in:
parent
58dde6837f
commit
e4abd6f4dc
@ -6,12 +6,12 @@ const { Database } = require('@strapi/database');
|
||||
|
||||
const loadConfiguration = require('./core/app-configuration');
|
||||
|
||||
const { createServer } = require('./server');
|
||||
const { createContainer } = require('./container');
|
||||
const utils = require('./utils');
|
||||
const initializeMiddlewares = require('./middlewares');
|
||||
const createStrapiFs = require('./services/fs');
|
||||
const createEventHub = require('./services/event-hub');
|
||||
const { createServer } = require('./services/server');
|
||||
const createWebhookRunner = require('./services/webhook-runner');
|
||||
const { webhookModel, createWebhookStore } = require('./services/webhook-store');
|
||||
const { createCoreStore, coreStoreModel } = require('./services/core-store');
|
||||
|
||||
94
packages/core/strapi/lib/services/server/compose-endpoint.js
Normal file
94
packages/core/strapi/lib/services/server/compose-endpoint.js
Normal file
@ -0,0 +1,94 @@
|
||||
'use strict';
|
||||
|
||||
const { toLower, castArray, trim } = require('lodash/fp');
|
||||
|
||||
const compose = require('koa-compose');
|
||||
const { validateRouteConfig } = require('./route');
|
||||
const { resolveMiddlewares } = require('./middleware');
|
||||
const { resolvePolicies } = require('./policy');
|
||||
|
||||
const getMethod = route => trim(toLower(route.method));
|
||||
const getPath = route => trim(route.path);
|
||||
|
||||
module.exports = strapi => {
|
||||
return (routeConfig, { pluginName, router, apiName }) => {
|
||||
validateRouteConfig(routeConfig);
|
||||
|
||||
try {
|
||||
const method = getMethod(routeConfig);
|
||||
const path = getPath(routeConfig);
|
||||
|
||||
const middlewares = resolveMiddlewares(routeConfig);
|
||||
const policies = resolvePolicies(routeConfig, { pluginName, apiName });
|
||||
|
||||
const routeInfo = (ctx, next) => {
|
||||
if (typeof routeConfig.handler === 'string') {
|
||||
const [controllerName, actionName] = routeConfig.handler.split('.');
|
||||
ctx.request.route = {
|
||||
endpoint: `${method} ${path}`,
|
||||
controller: toLower(controllerName),
|
||||
action: toLower(actionName),
|
||||
verb: toLower(method),
|
||||
plugin: pluginName,
|
||||
};
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
|
||||
const auth = (ctx, next) => {
|
||||
return next();
|
||||
|
||||
// if (routeConfig.auth && routeConfig.auth.public === true) {
|
||||
// return next();
|
||||
// }
|
||||
|
||||
// const { credentials, isAuthenticated = false } = ({} = ctx.state.auth);
|
||||
|
||||
// if (!isAuthenticated) {
|
||||
// throw new ctx.unauthorized();
|
||||
// }
|
||||
|
||||
// check credentials scope with routeConfig scope
|
||||
};
|
||||
|
||||
const action = getAction(routeConfig, { pluginName, apiName }, strapi);
|
||||
const handler = compose([routeInfo, auth, ...policies, ...middlewares, ...castArray(action)]);
|
||||
|
||||
router[method](path, handler);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Error creating endpoint ${routeConfig.method} ${routeConfig.path}: ${error.message}`
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const getController = (name, { pluginName, apiName }, strapi) => {
|
||||
if (pluginName) {
|
||||
if (pluginName === 'admin') {
|
||||
return strapi.controller(`admin::${name}`);
|
||||
}
|
||||
return strapi.plugin(pluginName).controller(name);
|
||||
} else if (apiName) {
|
||||
return strapi.controller(`api::${apiName}.${name}`);
|
||||
}
|
||||
|
||||
return strapi.controller(name);
|
||||
};
|
||||
|
||||
const getAction = ({ handler }, { pluginName, apiName }, strapi) => {
|
||||
if (Array.isArray(handler) || typeof handler === 'function') {
|
||||
return handler;
|
||||
}
|
||||
|
||||
const [controllerName, actionName] = trim(handler).split('.');
|
||||
|
||||
const controller = getController(toLower(controllerName), { pluginName, apiName }, strapi);
|
||||
|
||||
if (typeof controller[actionName] !== 'function') {
|
||||
throw new Error(`Handler not found "${handler}"`);
|
||||
}
|
||||
|
||||
return controller[actionName].bind(controller);
|
||||
};
|
||||
@ -6,7 +6,7 @@ const Router = require('@koa/router');
|
||||
|
||||
const { createHTTPServer } = require('./http-server');
|
||||
|
||||
const createEndpointComposer = require('./utils/compose-endpoint');
|
||||
const createEndpointComposer = require('./compose-endpoint');
|
||||
|
||||
const createRouteManager = strapi => {
|
||||
const composeEndpoint = createEndpointComposer(strapi);
|
||||
@ -95,7 +95,7 @@ const createServer = strapi => {
|
||||
|
||||
const apis = {
|
||||
admin: createAPI(strapi, { prefix: '/admin' }),
|
||||
// TODO: set prefix to api
|
||||
// { prefix: strapi.config.get('api.prefix', '/api') }
|
||||
'content-api': createAPI(strapi),
|
||||
};
|
||||
|
||||
27
packages/core/strapi/lib/services/server/middleware.js
Normal file
27
packages/core/strapi/lib/services/server/middleware.js
Normal file
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const { propOr } = require('lodash/fp');
|
||||
|
||||
const getMiddlewareConfig = propOr([], 'config.middlewares');
|
||||
|
||||
const resolveMiddlewares = route => {
|
||||
const middlewaresConfig = getMiddlewareConfig(route);
|
||||
|
||||
return middlewaresConfig.map(middlewareConfig => {
|
||||
if (typeof middlewareConfig === 'function') {
|
||||
return middlewareConfig;
|
||||
}
|
||||
|
||||
const middleware = strapi.middleware(middlewareConfig);
|
||||
|
||||
if (!middleware) {
|
||||
throw new Error(`Middleware ${middlewareConfig} not found.`);
|
||||
}
|
||||
|
||||
return middleware;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
resolveMiddlewares,
|
||||
};
|
||||
19
packages/core/strapi/lib/services/server/policy.js
Normal file
19
packages/core/strapi/lib/services/server/policy.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const { propOr } = require('lodash/fp');
|
||||
const policy = require('@strapi/utils/lib/policy');
|
||||
|
||||
const { bodyPolicy } = policy;
|
||||
|
||||
const getPoliciesConfig = propOr([], 'config.policies');
|
||||
|
||||
const resolvePolicies = (route, opts = {}) => {
|
||||
const policiesConfig = getPoliciesConfig(route);
|
||||
|
||||
const policies = policiesConfig.map(policyName => policy.get(policyName, opts));
|
||||
return [...policies, bodyPolicy];
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
resolvePolicies,
|
||||
};
|
||||
69
packages/core/strapi/lib/services/server/route.js
Normal file
69
packages/core/strapi/lib/services/server/route.js
Normal file
@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
|
||||
const { yup } = require('@strapi/utils');
|
||||
|
||||
const policyOrMiddlewareSchema = yup.lazy(value => {
|
||||
if (typeof value === 'string') {
|
||||
return yup.string().required();
|
||||
}
|
||||
|
||||
if (typeof value === 'function') {
|
||||
return yup.mixed().isFunction();
|
||||
}
|
||||
|
||||
return yup.object({
|
||||
name: yup.string().required(),
|
||||
options: yup.object().notRequired(), // any options
|
||||
});
|
||||
});
|
||||
|
||||
const routeSchema = yup.object({
|
||||
method: yup
|
||||
.string()
|
||||
.oneOf(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'ALL'])
|
||||
.required(),
|
||||
path: yup.string().required(),
|
||||
handler: yup.lazy(value => {
|
||||
if (typeof value === 'string') {
|
||||
return yup.string().required();
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return yup.array().required();
|
||||
}
|
||||
|
||||
return yup
|
||||
.mixed()
|
||||
.isFunction()
|
||||
.required();
|
||||
}),
|
||||
config: yup
|
||||
.object({
|
||||
policies: yup
|
||||
.array()
|
||||
.of(policyOrMiddlewareSchema)
|
||||
.notRequired(),
|
||||
middlwares: yup
|
||||
.array()
|
||||
.of(policyOrMiddlewareSchema)
|
||||
.notRequired(),
|
||||
})
|
||||
.notRequired(),
|
||||
});
|
||||
|
||||
const validateRouteConfig = routeConfig => {
|
||||
try {
|
||||
return routeSchema.validateSync(routeConfig, {
|
||||
strict: true,
|
||||
abortEarly: false,
|
||||
stripUnknown: true,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw new Error('Invalid route config');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
validateRouteConfig,
|
||||
};
|
||||
@ -1,191 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const compose = require('koa-compose');
|
||||
const { yup, policy: policyUtils } = require('@strapi/utils');
|
||||
|
||||
const { bodyPolicy } = policyUtils;
|
||||
|
||||
const policyOrMiddlewareSchema = yup.lazy(value => {
|
||||
if (typeof value === 'string') {
|
||||
return yup.string().required();
|
||||
}
|
||||
|
||||
if (typeof value === 'function') {
|
||||
return yup.mixed().isFunction();
|
||||
}
|
||||
|
||||
return yup.object({
|
||||
name: yup.string().required(),
|
||||
options: yup.object().notRequired(), // any options
|
||||
});
|
||||
});
|
||||
|
||||
const routeSchema = yup.object({
|
||||
method: yup
|
||||
.string()
|
||||
.oneOf(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'ALL'])
|
||||
.required(),
|
||||
path: yup.string().required(),
|
||||
handler: yup.lazy(value => {
|
||||
if (typeof value === 'string') {
|
||||
return yup.string().required();
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return yup.array().required();
|
||||
}
|
||||
|
||||
return yup
|
||||
.mixed()
|
||||
.isFunction()
|
||||
.required();
|
||||
}),
|
||||
config: yup
|
||||
.object({
|
||||
policies: yup
|
||||
.array()
|
||||
.of(policyOrMiddlewareSchema)
|
||||
.notRequired(),
|
||||
middlwares: yup
|
||||
.array()
|
||||
.of(policyOrMiddlewareSchema)
|
||||
.notRequired(),
|
||||
})
|
||||
.notRequired(),
|
||||
});
|
||||
|
||||
const validateRouteConfig = routeConfig => {
|
||||
try {
|
||||
return routeSchema.validateSync(routeConfig, {
|
||||
strict: true,
|
||||
abortEarly: false,
|
||||
stripUnknown: true,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw new Error('Invalid route config');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = strapi => {
|
||||
const routerChecker = createRouteChecker(strapi);
|
||||
|
||||
return (routeConfig, { pluginName, router, apiName }) => {
|
||||
validateRouteConfig(routeConfig);
|
||||
|
||||
try {
|
||||
const middlewares = resolveMiddlewares(routeConfig);
|
||||
|
||||
const { method, endpoint, policies, action } = routerChecker(routeConfig, {
|
||||
pluginName,
|
||||
apiName,
|
||||
});
|
||||
|
||||
if (_.isUndefined(action)) {
|
||||
return strapi.log.warn(
|
||||
`Ignored attempt to bind route '${routeConfig.method} ${routeConfig.path}' to unknown controller/action.`
|
||||
);
|
||||
}
|
||||
|
||||
router[method](endpoint, compose([...policies, ...middlewares, ..._.castArray(action)]));
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Error creating endpoint ${routeConfig.method} ${routeConfig.path}: ${error.message}`
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const resolveMiddlewares = route => {
|
||||
const middlewaresConfig = _.get(route, 'config.middlewares', []);
|
||||
|
||||
return middlewaresConfig.map(middlewareConfig => {
|
||||
if (typeof middlewareConfig === 'function') {
|
||||
return middlewareConfig;
|
||||
}
|
||||
|
||||
const middleware = strapi.middleware(middlewareConfig);
|
||||
|
||||
if (!middleware) {
|
||||
throw new Error(`Middleware ${middlewareConfig} not found.`);
|
||||
}
|
||||
|
||||
return middleware;
|
||||
});
|
||||
};
|
||||
|
||||
const getMethod = route => _.trim(_.toLower(route.method));
|
||||
const getEndpoint = route => _.trim(route.path);
|
||||
|
||||
const getAction = ({ method, endpoint, handler }, { pluginName, apiName }, strapi) => {
|
||||
// Define controller and action names.
|
||||
const [controllerName, actionName] = _.trim(handler).split('.');
|
||||
const controllerKey = _.toLower(controllerName);
|
||||
|
||||
let controller;
|
||||
|
||||
if (pluginName) {
|
||||
if (pluginName === 'admin') {
|
||||
controller = strapi.admin.controllers[controllerKey];
|
||||
} else {
|
||||
controller = strapi.plugin(pluginName).controller(controllerKey);
|
||||
}
|
||||
} else {
|
||||
controller = strapi.container.get('controllers').get(`api::${apiName}.${controllerKey}`);
|
||||
}
|
||||
if (!_.isFunction(controller[actionName])) {
|
||||
strapi.stopWithError(
|
||||
`Error creating endpoint ${method} ${endpoint}: handler not found "${controllerKey}.${actionName}"`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
action: controller[actionName].bind(controller),
|
||||
actionName,
|
||||
controllerKey,
|
||||
};
|
||||
};
|
||||
|
||||
const createRouteChecker = strapi => {
|
||||
return (value, { pluginName, apiName }) => {
|
||||
const { handler } = value;
|
||||
const method = getMethod(value);
|
||||
const endpoint = getEndpoint(value);
|
||||
const policies = [];
|
||||
let action;
|
||||
|
||||
if (Array.isArray(handler) || typeof handler === 'function') {
|
||||
action = handler;
|
||||
} else {
|
||||
const actionInfo = getAction({ method, endpoint, handler }, { pluginName, apiName }, strapi);
|
||||
action = actionInfo.action;
|
||||
|
||||
const globalPolicy = policyUtils.globalPolicy({
|
||||
controller: actionInfo.controllerKey,
|
||||
action: actionInfo.actionName,
|
||||
method,
|
||||
endpoint,
|
||||
plugin: pluginName,
|
||||
});
|
||||
|
||||
policies.push(globalPolicy);
|
||||
}
|
||||
|
||||
const policyOption = _.get(value, 'config.policies', []);
|
||||
|
||||
const routePolicies = policyOption.map(policyConfig =>
|
||||
policyUtils.get(policyConfig, { pluginName, apiName })
|
||||
);
|
||||
|
||||
// Init policies array.
|
||||
policies.push(...routePolicies, bodyPolicy);
|
||||
|
||||
return {
|
||||
method,
|
||||
endpoint,
|
||||
policies,
|
||||
action,
|
||||
};
|
||||
};
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user