mirror of
https://github.com/strapi/strapi.git
synced 2025-12-30 00:37:24 +00:00
Use koa-router and fix graphql-uploads
This commit is contained in:
parent
a148c43758
commit
7c5f1484ba
@ -7,10 +7,7 @@
|
||||
},
|
||||
"options": {
|
||||
"increments": true,
|
||||
"timestamps": [
|
||||
"created_at",
|
||||
"updated_at"
|
||||
],
|
||||
"timestamps": ["created_at", "updated_at"],
|
||||
"comment": ""
|
||||
},
|
||||
"attributes": {
|
||||
@ -20,6 +17,11 @@
|
||||
"minLength": 5,
|
||||
"type": "string"
|
||||
},
|
||||
"cover": {
|
||||
"model": "file",
|
||||
"via": "related",
|
||||
"plugin": "upload"
|
||||
},
|
||||
"menu": {
|
||||
"model": "menu",
|
||||
"via": "restaurant"
|
||||
@ -31,13 +33,7 @@
|
||||
"model": "address"
|
||||
},
|
||||
"price_range": {
|
||||
"enum": [
|
||||
"very_cheap",
|
||||
"cheap",
|
||||
"average",
|
||||
"expensive",
|
||||
"very_expensive"
|
||||
],
|
||||
"enum": ["very_cheap", "cheap", "average", "expensive", "very_expensive"],
|
||||
"type": "enumeration"
|
||||
},
|
||||
"description": {
|
||||
@ -63,4 +59,4 @@
|
||||
"type": "group"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,29 +28,7 @@
|
||||
"mode": "block"
|
||||
},
|
||||
"cors": {
|
||||
"enabled": true,
|
||||
"origin": "*",
|
||||
"expose": [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
],
|
||||
"maxAge": 31536000,
|
||||
"credentials": true,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"OPTIONS",
|
||||
"HEAD"
|
||||
],
|
||||
"headers": [
|
||||
"Content-Type",
|
||||
"Authorization",
|
||||
"X-Frame-Options",
|
||||
"Origin"
|
||||
]
|
||||
"enabled": true
|
||||
},
|
||||
"ip": {
|
||||
"enabled": false,
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
},
|
||||
"csp": {
|
||||
"enabled": true,
|
||||
"policy": [{
|
||||
"policy": [
|
||||
{
|
||||
"img-src": "'self' http:"
|
||||
},
|
||||
"block-all-mixed-content"
|
||||
@ -30,29 +31,7 @@
|
||||
"mode": "block"
|
||||
},
|
||||
"cors": {
|
||||
"enabled": true,
|
||||
"origin": "*",
|
||||
"expose": [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
],
|
||||
"maxAge": 31536000,
|
||||
"credentials": true,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"OPTIONS",
|
||||
"HEAD"
|
||||
],
|
||||
"headers": [
|
||||
"Content-Type",
|
||||
"Authorization",
|
||||
"X-Frame-Options",
|
||||
"Origin"
|
||||
]
|
||||
"enabled": true
|
||||
},
|
||||
"ip": {
|
||||
"enabled": false,
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
},
|
||||
"csp": {
|
||||
"enabled": true,
|
||||
"policy": [{
|
||||
"policy": [
|
||||
{
|
||||
"img-src": "'self' http:"
|
||||
},
|
||||
"block-all-mixed-content"
|
||||
@ -30,29 +31,7 @@
|
||||
"mode": "block"
|
||||
},
|
||||
"cors": {
|
||||
"enabled": true,
|
||||
"origin": "*",
|
||||
"expose": [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
],
|
||||
"maxAge": 31536000,
|
||||
"credentials": true,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"OPTIONS",
|
||||
"HEAD"
|
||||
],
|
||||
"headers": [
|
||||
"Content-Type",
|
||||
"Authorization",
|
||||
"X-Frame-Options",
|
||||
"Origin"
|
||||
]
|
||||
"enabled": true
|
||||
},
|
||||
"ip": {
|
||||
"enabled": false,
|
||||
|
||||
@ -28,29 +28,7 @@
|
||||
"mode": "block"
|
||||
},
|
||||
"cors": {
|
||||
"enabled": true,
|
||||
"origin": "*",
|
||||
"expose": [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
],
|
||||
"maxAge": 31536000,
|
||||
"credentials": true,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"OPTIONS",
|
||||
"HEAD"
|
||||
],
|
||||
"headers": [
|
||||
"Content-Type",
|
||||
"Authorization",
|
||||
"X-Frame-Options",
|
||||
"Origin"
|
||||
]
|
||||
"enabled": true
|
||||
},
|
||||
"ip": {
|
||||
"enabled": false,
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
},
|
||||
"csp": {
|
||||
"enabled": true,
|
||||
"policy": [{
|
||||
"policy": [
|
||||
{
|
||||
"img-src": "'self' http:"
|
||||
},
|
||||
"block-all-mixed-content"
|
||||
@ -30,29 +31,7 @@
|
||||
"mode": "block"
|
||||
},
|
||||
"cors": {
|
||||
"enabled": true,
|
||||
"origin": "*",
|
||||
"expose": [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
],
|
||||
"maxAge": 31536000,
|
||||
"credentials": true,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"OPTIONS",
|
||||
"HEAD"
|
||||
],
|
||||
"headers": [
|
||||
"Content-Type",
|
||||
"Authorization",
|
||||
"X-Frame-Options",
|
||||
"Origin"
|
||||
]
|
||||
"enabled": true
|
||||
},
|
||||
"ip": {
|
||||
"enabled": false,
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
},
|
||||
"csp": {
|
||||
"enabled": true,
|
||||
"policy": [{
|
||||
"policy": [
|
||||
{
|
||||
"img-src": "'self' http:"
|
||||
},
|
||||
"block-all-mixed-content"
|
||||
@ -30,29 +31,7 @@
|
||||
"mode": "block"
|
||||
},
|
||||
"cors": {
|
||||
"enabled": true,
|
||||
"origin": "*",
|
||||
"expose": [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
],
|
||||
"maxAge": 31536000,
|
||||
"credentials": true,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"OPTIONS",
|
||||
"HEAD"
|
||||
],
|
||||
"headers": [
|
||||
"Content-Type",
|
||||
"Authorization",
|
||||
"X-Frame-Options",
|
||||
"Origin"
|
||||
]
|
||||
"enabled": true
|
||||
},
|
||||
"ip": {
|
||||
"enabled": false,
|
||||
|
||||
@ -52,9 +52,7 @@ function checkTokenValidity(response) {
|
||||
if (auth.getToken()) {
|
||||
return fetch(`${strapi.backendURL}/users/me`, options).then(() => {
|
||||
if (response.status === 401) {
|
||||
window.location = `${
|
||||
strapi.remoteURL
|
||||
}/plugins/users-permissions/auth/login`;
|
||||
window.location = `${strapi.remoteURL}/plugins/users-permissions/auth/login`;
|
||||
|
||||
auth.clearAppStorage();
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ const uploadFiles = require('../../utils/upload-files');
|
||||
|
||||
module.exports = async (ctx, next) => {
|
||||
const { source } = ctx.request.query;
|
||||
const { model } = ctx.request.params;
|
||||
const { model } = ctx.params;
|
||||
|
||||
const target = source === 'admin' ? strapi.admin : strapi.plugins[source];
|
||||
|
||||
|
||||
@ -48,28 +48,23 @@ module.exports = strapi => {
|
||||
])
|
||||
) {
|
||||
route.config.prefix = '';
|
||||
route.path = `/${
|
||||
strapi.plugins.documentation.config['x-strapi-config'].path
|
||||
}${route.path}`.replace('//', '/');
|
||||
route.path = `/${strapi.plugins.documentation.config['x-strapi-config'].path}${route.path}`.replace(
|
||||
'//',
|
||||
'/'
|
||||
);
|
||||
}
|
||||
|
||||
return route;
|
||||
}
|
||||
);
|
||||
|
||||
strapi.router.route({
|
||||
method: 'GET',
|
||||
path: '/plugins/documentation/*.*',
|
||||
handler: [
|
||||
async (ctx, next) => {
|
||||
ctx.url = path.basename(ctx.url);
|
||||
strapi.router.get('/plugins/documentation/*', async (ctx, next) => {
|
||||
ctx.url = path.basename(ctx.url);
|
||||
|
||||
return await koaStatic(swaggerUi.getAbsoluteFSPath(), {
|
||||
maxage: strapi.config.middleware.settings.public.maxAge,
|
||||
defer: true,
|
||||
})(ctx, next);
|
||||
},
|
||||
],
|
||||
return await koaStatic(swaggerUi.getAbsoluteFSPath(), {
|
||||
maxage: strapi.config.middleware.settings.public.maxAge,
|
||||
defer: true,
|
||||
})(ctx, next);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@ -81,6 +81,8 @@ module.exports = strapi => {
|
||||
validationRules: [depthLimit(strapi.plugins.graphql.config.depthLimit)],
|
||||
tracing: _.get(strapi.plugins.graphql, 'config.tracing', false),
|
||||
playground: false,
|
||||
cors: false,
|
||||
bodyParserConfig: true,
|
||||
};
|
||||
|
||||
// Disable GraphQL Playground in production environment.
|
||||
|
||||
@ -59,7 +59,7 @@ function* uploadFiles(action) {
|
||||
'/upload',
|
||||
{ method: 'POST', headers, body: action.formData },
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
const newFiles = response.map(file => Map(file));
|
||||
|
||||
@ -103,10 +103,10 @@ function* search() {
|
||||
: '/upload/files';
|
||||
const params = isEmpty(search)
|
||||
? {
|
||||
_limit: pageParams._limit,
|
||||
_sort: pageParams._sort,
|
||||
_start,
|
||||
}
|
||||
_limit: pageParams._limit,
|
||||
_sort: pageParams._sort,
|
||||
_start,
|
||||
}
|
||||
: {};
|
||||
const response = yield call(request, requestURL, { method: 'GET', params });
|
||||
const entries = response.length === 0 ? [] : response.map(obj => Map(obj));
|
||||
|
||||
@ -1,44 +1,120 @@
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const crypto = require('crypto');
|
||||
const toArray = require('stream-to-array');
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
function niceHash(buffer) {
|
||||
return crypto
|
||||
.createHash('sha256')
|
||||
.update(buffer)
|
||||
.digest('base64')
|
||||
.replace(/=/g, '')
|
||||
.replace(/\//g, '-')
|
||||
.replace(/\+/, '_');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mutation: `
|
||||
upload(refId: ID, ref: String, source: String, file: Upload!): UploadFile!
|
||||
upload(refId: ID, ref: String, field: String, source: String, file: Upload!): UploadFile!
|
||||
multipleUpload(refId: ID, ref: String, field: String, source: String, files: [Upload]!): [UploadFile]!
|
||||
`,
|
||||
resolver: {
|
||||
Query: {
|
||||
file: false,
|
||||
files: {
|
||||
resolver: 'Upload.find'
|
||||
}
|
||||
resolver: 'Upload.find',
|
||||
},
|
||||
},
|
||||
Mutation: {
|
||||
createFile: false,
|
||||
updateFile: false,
|
||||
deleteFile: false,
|
||||
upload: {
|
||||
description: 'Upload one or many files',
|
||||
resolver: async (obj, { file, ...fields}, { context }) => {
|
||||
// Construct context to fit with koa-parser guidelines
|
||||
// and avoid to update our business logic too much.
|
||||
context.request.body = {
|
||||
files: {
|
||||
files: await file
|
||||
},
|
||||
fields
|
||||
};
|
||||
description: 'Upload one file',
|
||||
resolver: async (obj, { file: upload, ...fields }) => {
|
||||
const file = await formatFile(upload, fields);
|
||||
|
||||
// Call controller action.
|
||||
await strapi.plugins.upload.controllers.upload.upload(context);
|
||||
const config = await strapi
|
||||
.store({
|
||||
environment: strapi.config.environment,
|
||||
type: 'plugin',
|
||||
name: 'upload',
|
||||
})
|
||||
.get({ key: 'provider' });
|
||||
|
||||
// Handle case when the user is uploading only one file.
|
||||
if (_.isArray(context.body) && context.body.length === 1) {
|
||||
return context.body[0];
|
||||
}
|
||||
const uploadedFiles = await strapi.plugins.upload.services.upload.upload(
|
||||
[file],
|
||||
config
|
||||
);
|
||||
|
||||
// Return response.
|
||||
return context.body;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uploadedFiles.length === 1 ? uploadedFiles[0] : uploadedFiles;
|
||||
},
|
||||
},
|
||||
multipleUpload: {
|
||||
description: 'Upload one file',
|
||||
resolver: async (obj, { files: uploads, ...fields }) => {
|
||||
const files = await Promise.all(
|
||||
uploads.map(upload => formatFile(upload, fields))
|
||||
);
|
||||
|
||||
const config = await strapi
|
||||
.store({
|
||||
environment: strapi.config.environment,
|
||||
type: 'plugin',
|
||||
name: 'upload',
|
||||
})
|
||||
.get({ key: 'provider' });
|
||||
|
||||
const uploadedFiles = await strapi.plugins.upload.services.upload.upload(
|
||||
files,
|
||||
config
|
||||
);
|
||||
|
||||
// Return response.
|
||||
return uploadedFiles;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const formatFile = async (upload, fields) => {
|
||||
const { filename, mimetype, createReadStream } = await upload;
|
||||
|
||||
const stream = createReadStream();
|
||||
|
||||
const parts = await toArray(stream);
|
||||
const buffers = parts.map(part =>
|
||||
_.isBuffer(part) ? part : Buffer.from(part)
|
||||
);
|
||||
|
||||
const buffer = Buffer.concat(buffers);
|
||||
|
||||
const fileData = {
|
||||
name: filename,
|
||||
sha256: niceHash(buffer),
|
||||
hash: uuid().replace(/-/g, ''),
|
||||
ext: path.extname(filename),
|
||||
buffer,
|
||||
mime: mimetype,
|
||||
size: (buffer.length / 1000).toFixed(2),
|
||||
};
|
||||
|
||||
const { refId, ref, source, field } = fields;
|
||||
|
||||
// Add details to the file to be able to create the relationships.
|
||||
if (refId && ref && field) {
|
||||
fileData.related = [
|
||||
{
|
||||
refId,
|
||||
ref,
|
||||
source,
|
||||
field,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return fileData;
|
||||
};
|
||||
|
||||
@ -83,7 +83,9 @@ module.exports = {
|
||||
const res = await strapi.plugins['upload'].services.upload.add(file);
|
||||
|
||||
// Remove temp file
|
||||
fs.unlinkSync(file.tmpPath);
|
||||
if (file.tmpPath) {
|
||||
fs.unlinkSync(file.tmpPath);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ const path = require('path');
|
||||
const { EventEmitter } = require('events');
|
||||
const fse = require('fs-extra');
|
||||
const Koa = require('koa');
|
||||
const Router = require('koa-router');
|
||||
const _ = require('lodash');
|
||||
const { logger, models } = require('strapi-utils');
|
||||
const utils = require('./utils');
|
||||
@ -64,6 +65,7 @@ class Strapi extends EventEmitter {
|
||||
|
||||
// Expose `koa`.
|
||||
this.app = new Koa();
|
||||
this.router = new Router();
|
||||
|
||||
// Mount the HTTP server.
|
||||
this.server = http.createServer(this.app.callback());
|
||||
@ -151,6 +153,8 @@ class Strapi extends EventEmitter {
|
||||
// Init first start
|
||||
utils.init(this.config);
|
||||
|
||||
this.app.use(this.router.routes()).use(this.router.allowedMethods());
|
||||
|
||||
// Launch server.
|
||||
this.server.listen(this.config.port, async err => {
|
||||
if (err) return this.stopWithError(err);
|
||||
@ -315,11 +319,8 @@ class Strapi extends EventEmitter {
|
||||
initCoreStore(this);
|
||||
|
||||
// Initialize hooks and middlewares.
|
||||
|
||||
await Promise.all([
|
||||
initializeMiddlewares.call(this),
|
||||
initializeHooks.call(this),
|
||||
]);
|
||||
await initializeMiddlewares.call(this);
|
||||
await initializeHooks.call(this);
|
||||
}
|
||||
|
||||
reload() {
|
||||
|
||||
4
packages/strapi/lib/core/bootstrap.js
vendored
4
packages/strapi/lib/core/bootstrap.js
vendored
@ -4,7 +4,6 @@ const _ = require('lodash');
|
||||
|
||||
const { createController, createService } = require('../core-api');
|
||||
const getURLFromSegments = require('../utils/url-from-segments');
|
||||
const routerJoi = require('koa-joi-router');
|
||||
|
||||
module.exports = function(strapi) {
|
||||
// Retrieve Strapi version.
|
||||
@ -38,9 +37,6 @@ module.exports = function(strapi) {
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize main router to use it in middlewares.
|
||||
strapi.router = routerJoi();
|
||||
|
||||
Object.keys(strapi.groups).forEach(key => {
|
||||
const group = strapi.groups[key];
|
||||
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
{
|
||||
"cors": {
|
||||
"enabled": false,
|
||||
"origin": "*",
|
||||
"expose": [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
],
|
||||
"maxAge": 31536000,
|
||||
"credentials": true,
|
||||
"methods": [
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"PATCH",
|
||||
"DELETE",
|
||||
"HEAD",
|
||||
"OPTIONS"
|
||||
],
|
||||
"headers": [
|
||||
"Content-Type",
|
||||
"Authorization",
|
||||
"X-Forwarded-Host"
|
||||
],
|
||||
"keepHeadersOnError": false
|
||||
}
|
||||
}
|
||||
@ -3,59 +3,47 @@
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
const cors = require('@koa/cors');
|
||||
|
||||
/**
|
||||
* CORS hook
|
||||
*/
|
||||
|
||||
const defaults = require('./defaults.json');
|
||||
const kcors = require('kcors');
|
||||
const defaults = {
|
||||
origin: '*',
|
||||
maxAge: 31536000,
|
||||
credentials: true,
|
||||
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
|
||||
headers: ['Content-Type', 'Authorization', 'Origin', 'Accept'],
|
||||
keepHeadersOnError: false,
|
||||
};
|
||||
|
||||
module.exports = strapi => {
|
||||
return {
|
||||
/**
|
||||
* Initialize the hook
|
||||
*/
|
||||
|
||||
initialize() {
|
||||
strapi.app.use(async (ctx, next) => {
|
||||
if (ctx.request.admin) {
|
||||
return kcors({
|
||||
origin: '*',
|
||||
exposeHeaders: defaults.cors.expose,
|
||||
maxAge: defaults.cors.maxAge,
|
||||
credentials: defaults.cors.credentials,
|
||||
allowMethods: defaults.cors.methods,
|
||||
allowHeaders: defaults.cors.headers,
|
||||
keepHeadersOnError: defaults.cors.keepHeadersOnError,
|
||||
})(ctx, next);
|
||||
} else if (strapi.config.currentEnvironment.security.cors.enabled) {
|
||||
return kcors({
|
||||
origin: function(ctx) {
|
||||
const whitelist = strapi.config.middleware.settings.cors.origin.split(
|
||||
/\s*,\s*/
|
||||
);
|
||||
const requestOrigin = ctx.accept.headers.origin;
|
||||
if (whitelist.includes('*')) {
|
||||
return '*';
|
||||
}
|
||||
if (!whitelist.includes(requestOrigin)) {
|
||||
return ctx.throw(`${requestOrigin} is not a valid origin`);
|
||||
}
|
||||
return requestOrigin;
|
||||
},
|
||||
exposeHeaders: strapi.config.middleware.settings.cors.expose,
|
||||
maxAge: strapi.config.middleware.settings.cors.maxAge,
|
||||
credentials: strapi.config.middleware.settings.cors.credentials,
|
||||
allowMethods: strapi.config.middleware.settings.cors.methods,
|
||||
allowHeaders: strapi.config.middleware.settings.cors.headers,
|
||||
keepHeadersOnError:
|
||||
strapi.config.middleware.settings.cors.keepHeadersOnError,
|
||||
})(ctx, next);
|
||||
}
|
||||
if (strapi.config.currentEnvironment.security.cors.enabled !== true)
|
||||
return;
|
||||
|
||||
await next();
|
||||
});
|
||||
const {
|
||||
origin,
|
||||
expose,
|
||||
maxAge,
|
||||
credentials,
|
||||
methods,
|
||||
headers,
|
||||
keepHeadersOnError,
|
||||
} = Object.assign({}, defaults, strapi.config.middleware.settings.cors);
|
||||
|
||||
strapi.app.use(
|
||||
cors({
|
||||
origin,
|
||||
exposeHeaders: expose,
|
||||
maxAge,
|
||||
credentials,
|
||||
allowMethods: methods,
|
||||
allowHeaders: headers,
|
||||
keepHeadersOnError,
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -3,17 +3,6 @@
|
||||
const { uniq, difference, get, isUndefined, merge } = require('lodash');
|
||||
|
||||
module.exports = async function() {
|
||||
// Set if is admin destination for middleware application.
|
||||
this.app.use(async (ctx, next) => {
|
||||
if (ctx.request.header['origin'] === 'http://localhost:4000') {
|
||||
ctx.request.header['x-forwarded-host'] = 'strapi';
|
||||
}
|
||||
|
||||
ctx.request.admin = ctx.request.header['x-forwarded-host'] === 'strapi';
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
/** Utils */
|
||||
|
||||
const middlewareConfig = this.config.middleware;
|
||||
|
||||
@ -13,12 +13,16 @@ module.exports = strapi => {
|
||||
*/
|
||||
|
||||
initialize() {
|
||||
strapi.app.use(
|
||||
body({
|
||||
strapi.app.use((ctx, next) => {
|
||||
// disable for graphql
|
||||
// TODO: find a better way later
|
||||
if (ctx.url === '/graphql') return next();
|
||||
|
||||
return body({
|
||||
patchKoa: true,
|
||||
...strapi.config.middleware.settings.parser,
|
||||
})
|
||||
);
|
||||
})(ctx, next);
|
||||
});
|
||||
|
||||
qs(strapi.app);
|
||||
},
|
||||
|
||||
@ -29,41 +29,34 @@ module.exports = strapi => {
|
||||
);
|
||||
|
||||
// Serve /public index page.
|
||||
strapi.router.route({
|
||||
method: 'GET',
|
||||
path: '/',
|
||||
handler: [
|
||||
async (ctx, next) => {
|
||||
ctx.url = path.basename(`${ctx.url}/index.html`);
|
||||
|
||||
await next();
|
||||
},
|
||||
koaStatic(staticDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
strapi.router.get(
|
||||
'/',
|
||||
async (ctx, next) => {
|
||||
ctx.url = path.basename(`${ctx.url}/index.html`);
|
||||
await next();
|
||||
},
|
||||
koaStatic(staticDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Match every route with an extension.
|
||||
// The file without extension will not be served.
|
||||
// Note: This route could be override by the user.
|
||||
strapi.router.route({
|
||||
method: 'GET',
|
||||
path: '/*',
|
||||
handler: [
|
||||
async (ctx, next) => {
|
||||
const parse = path.parse(ctx.url);
|
||||
ctx.url = path.join(parse.dir, parse.base);
|
||||
strapi.router.get(
|
||||
'/*',
|
||||
async (ctx, next) => {
|
||||
const parse = path.parse(ctx.url);
|
||||
ctx.url = path.join(parse.dir, parse.base);
|
||||
|
||||
await next();
|
||||
},
|
||||
koaStatic(staticDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
await next();
|
||||
},
|
||||
koaStatic(staticDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
})
|
||||
);
|
||||
|
||||
const basename = _.get(
|
||||
strapi.config.currentEnvironment.server,
|
||||
@ -75,59 +68,49 @@ module.exports = strapi => {
|
||||
const buildDir = path.resolve(strapi.dir, 'build');
|
||||
|
||||
// Serve /admin index page.
|
||||
strapi.router.route({
|
||||
method: 'GET',
|
||||
path: basename,
|
||||
handler: [
|
||||
async (ctx, next) => {
|
||||
ctx.url = 'index.html';
|
||||
|
||||
await next();
|
||||
},
|
||||
koaStatic(buildDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
strapi.router.get(
|
||||
basename,
|
||||
async (ctx, next) => {
|
||||
ctx.url = 'index.html';
|
||||
await next();
|
||||
},
|
||||
koaStatic(buildDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Allow refresh in admin page.
|
||||
strapi.router.route({
|
||||
method: 'GET',
|
||||
path: `${basename}/*`,
|
||||
handler: [
|
||||
async (ctx, next) => {
|
||||
const parse = path.parse(ctx.url);
|
||||
strapi.router.get(
|
||||
`${basename}/*`,
|
||||
async (ctx, next) => {
|
||||
const parse = path.parse(ctx.url);
|
||||
|
||||
if (parse.ext === '') {
|
||||
ctx.url = 'index.html';
|
||||
}
|
||||
if (parse.ext === '') {
|
||||
ctx.url = 'index.html';
|
||||
}
|
||||
|
||||
await next();
|
||||
},
|
||||
koaStatic(buildDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
await next();
|
||||
},
|
||||
koaStatic(buildDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Serve admin assets.
|
||||
strapi.router.route({
|
||||
method: 'GET',
|
||||
path: `${basename}/*.*`,
|
||||
handler: [
|
||||
async (ctx, next) => {
|
||||
ctx.url = path.basename(ctx.url);
|
||||
strapi.router.get(
|
||||
`${basename}/*.*`,
|
||||
async (ctx, next) => {
|
||||
ctx.url = path.basename(ctx.url);
|
||||
|
||||
await next();
|
||||
},
|
||||
koaStatic(buildDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
await next();
|
||||
},
|
||||
koaStatic(buildDir, {
|
||||
maxage: maxAge,
|
||||
defer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const routerJoi = require('koa-joi-router');
|
||||
const Router = require('koa-router');
|
||||
|
||||
/**
|
||||
* Router hook
|
||||
@ -32,26 +32,24 @@ module.exports = strapi => {
|
||||
if (!_.isEmpty(_.get(strapi.admin, 'config.routes', false))) {
|
||||
// Create router for admin.
|
||||
// Prefix router with the admin's name.
|
||||
const router = routerJoi();
|
||||
const router = new Router({
|
||||
prefix: '/admin',
|
||||
});
|
||||
|
||||
_.forEach(strapi.admin.config.routes, value => {
|
||||
composeEndpoint(value, null, router);
|
||||
});
|
||||
|
||||
// router.prefix(strapi.config.admin.path || `/${strapi.config.paths.admin}`);
|
||||
router.prefix('/admin');
|
||||
|
||||
// TODO:
|
||||
// - Mount on main router `strapi.router.use(routerAdmin.middleware());`
|
||||
|
||||
// Mount admin router on Strapi router
|
||||
strapi.app.use(router.middleware());
|
||||
strapi.app.use(router.routes()).use(router.allowedMethods());
|
||||
}
|
||||
|
||||
if (strapi.plugins) {
|
||||
// Parse each plugin's routes.
|
||||
_.forEach(strapi.plugins, (plugin, name) => {
|
||||
const router = routerJoi();
|
||||
const router = new Router({
|
||||
prefix: `/${name}`,
|
||||
});
|
||||
|
||||
// Exclude routes with prefix.
|
||||
const excludedRoutes = _.omitBy(
|
||||
@ -66,8 +64,6 @@ module.exports = strapi => {
|
||||
}
|
||||
);
|
||||
|
||||
router.prefix(`/${name}`);
|
||||
|
||||
// /!\ Could override main router's routes.
|
||||
if (!_.isEmpty(excludedRoutes)) {
|
||||
_.forEach(excludedRoutes, value => {
|
||||
@ -75,16 +71,10 @@ module.exports = strapi => {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// - Mount on main router `strapi.router.use(router.middleware());`
|
||||
|
||||
// Mount plugin router
|
||||
strapi.app.use(router.middleware());
|
||||
strapi.app.use(router.routes()).use(router.allowedMethods());
|
||||
});
|
||||
}
|
||||
|
||||
// Let the router use our routes and allowed methods.
|
||||
strapi.app.use(strapi.router.middleware());
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -13,11 +13,7 @@ module.exports = strapi => {
|
||||
|
||||
const endpoint = `${value.method} ${value.path}`;
|
||||
|
||||
const { policies, action, validate } = routerChecker(
|
||||
value,
|
||||
endpoint,
|
||||
plugin
|
||||
);
|
||||
const { policies, action } = routerChecker(value, endpoint, plugin);
|
||||
|
||||
if (_.isUndefined(action) || !_.isFunction(action)) {
|
||||
return strapi.log.warn(
|
||||
@ -25,16 +21,6 @@ module.exports = strapi => {
|
||||
);
|
||||
}
|
||||
|
||||
router.route(
|
||||
_.omitBy(
|
||||
{
|
||||
method: value.method,
|
||||
path: value.path,
|
||||
handler: _.remove([compose(policies), action], o => _.isFunction(o)),
|
||||
validate,
|
||||
},
|
||||
_.isEmpty
|
||||
)
|
||||
);
|
||||
router[value.method.toLowerCase()](value.path, compose(policies), action);
|
||||
};
|
||||
};
|
||||
|
||||
@ -10,13 +10,10 @@ const _ = require('lodash');
|
||||
// Strapi utilities.
|
||||
const finder = require('strapi-utils').finder;
|
||||
const regex = require('strapi-utils').regex;
|
||||
const joijson = require('strapi-utils').joijson;
|
||||
const policyUtils = require('strapi-utils').policy;
|
||||
const { Joi } = require('koa-joi-router');
|
||||
|
||||
module.exports = strapi =>
|
||||
function routerChecker(value, endpoint, plugin) {
|
||||
const builder = joijson.builder(Joi);
|
||||
const route = regex.detectRoute(endpoint);
|
||||
|
||||
// Define controller and action names.
|
||||
@ -74,30 +71,9 @@ module.exports = strapi =>
|
||||
}
|
||||
});
|
||||
|
||||
// Init validate.
|
||||
const validate = {};
|
||||
|
||||
if (
|
||||
_.isString(_.get(value, 'config.validate')) &&
|
||||
!_.isEmpty(_.get(value, 'config.validate'))
|
||||
) {
|
||||
const validator = _.get(
|
||||
strapi.api,
|
||||
currentApiName + '.validators.' + value.config.validate
|
||||
);
|
||||
|
||||
_.merge(
|
||||
validate,
|
||||
_.mapValues(validator, value => {
|
||||
return builder.build(value);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
route,
|
||||
policies,
|
||||
action,
|
||||
validate,
|
||||
};
|
||||
};
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
"strapi": "./bin/strapi.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@koa/cors": "^3.0.0",
|
||||
"async": "^2.1.2",
|
||||
"boom": "^7.3.0",
|
||||
"chalk": "^2.4.1",
|
||||
@ -22,7 +23,6 @@
|
||||
"fs-extra": "^7.0.0",
|
||||
"glob": "^7.1.2",
|
||||
"inquirer": "^6.2.1",
|
||||
"kcors": "^2.2.0",
|
||||
"koa": "^2.1.0",
|
||||
"koa-body": "^4.1.0",
|
||||
"koa-compose": "^4.0.0",
|
||||
@ -31,10 +31,10 @@
|
||||
"koa-favicon": "^2.0.0",
|
||||
"koa-i18n": "^2.1.0",
|
||||
"koa-ip": "^2.0.0",
|
||||
"koa-joi-router": "^6.0.0",
|
||||
"koa-locale": "~1.3.0",
|
||||
"koa-lusca": "~2.2.0",
|
||||
"koa-qs": "^2.0.0",
|
||||
"koa-router": "^7.4.0",
|
||||
"koa-session": "^5.5.1",
|
||||
"koa-static": "^4.0.1",
|
||||
"lodash": "^4.17.5",
|
||||
|
||||
86
yarn.lock
86
yarn.lock
@ -1024,15 +1024,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.0.2.tgz#f63a5ff00e891a4e7aa98f11119f9515c6672032"
|
||||
integrity sha512-O6o6mrV4P65vVccxymuruucb+GhP2zl9NLCG8OdoFRS8BEGw3vwpPp20wpAtpbQQxz1CEUtmxJGgWhjq1XA3qw==
|
||||
|
||||
"@hapi/joi@15.0.0":
|
||||
version "15.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.0.0.tgz#675d227b4c10d902fc5a96a2235665f0bc292e1b"
|
||||
integrity sha512-pLCfcSeT26g59jEKZntmzlqe19dRMDNxCFKGD4CriF8+9FAD3Mq1aWNuKIFpKpX+u3x8lxLKXolDwk0gYl3b2w==
|
||||
dependencies:
|
||||
"@hapi/address" "2.x.x"
|
||||
"@hapi/hoek" "6.x.x"
|
||||
"@hapi/topo" "3.x.x"
|
||||
|
||||
"@hapi/joi@^15.0.3":
|
||||
version "15.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.0.tgz#940cb749b5c55c26ab3b34ce362e82b6162c8e7a"
|
||||
@ -1208,6 +1199,13 @@
|
||||
dependencies:
|
||||
vary "^1.1.2"
|
||||
|
||||
"@koa/cors@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.0.0.tgz#df021b4df2dadf1e2b04d7c8ddf93ba2d42519cb"
|
||||
integrity sha512-hDp+cXj6vTYSwHRJfiSpnf5dTMv3FmqNKh1or9BPJk4SHOviHnK9GoL9dT0ypt/E+hlkRkZ9edHylcosW3Ghrw==
|
||||
dependencies:
|
||||
vary "^1.1.2"
|
||||
|
||||
"@lerna/add@3.16.2":
|
||||
version "3.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.16.2.tgz#90ecc1be7051cfcec75496ce122f656295bd6e94"
|
||||
@ -3497,14 +3495,6 @@ autoprefixer@^9.5.1, autoprefixer@^9.6.1:
|
||||
postcss "^7.0.17"
|
||||
postcss-value-parser "^4.0.0"
|
||||
|
||||
await-busboy@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/await-busboy/-/await-busboy-1.0.3.tgz#11b8941191c4b0fe5123988dab626ea88220119b"
|
||||
integrity sha512-u2TaZLepph/OHrJZgD/qu0vMFl17ahkTz4HJYbnaRLqJX6q1x8SMbFNV1nJnIYRbUr3jyHuTwaCN0hIKfMA8YA==
|
||||
dependencies:
|
||||
black-hole-stream "0.0.1"
|
||||
busboy "0.3.0"
|
||||
|
||||
aws-sdk@^2.382.0, aws-sdk@^2.457.0:
|
||||
version "2.498.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.498.0.tgz#42e05965166a01b45e026e4922926df4cd160fc5"
|
||||
@ -3790,11 +3780,6 @@ bl@~1.0.0:
|
||||
dependencies:
|
||||
readable-stream "~2.0.5"
|
||||
|
||||
black-hole-stream@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/black-hole-stream/-/black-hole-stream-0.0.1.tgz#33b7a06b9f1e7453d6041b82974481d2152aea42"
|
||||
integrity sha1-M7ega58edFPWBBuCl0SB0hUq6kI=
|
||||
|
||||
block-stream@*:
|
||||
version "0.0.9"
|
||||
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
|
||||
@ -4167,13 +4152,6 @@ builtins@^1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
|
||||
integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og=
|
||||
|
||||
busboy@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.0.tgz#6ee3cb1c844fc1f691d8f9d824f70128b3b5e485"
|
||||
integrity sha512-e+kzZRAbbvJPLjQz2z+zAyr78BSi9IFeBTyLwF76g78Q2zRt/RZ1NtS3MS17v2yLqYfLz69zHdC+1L4ja8PwqQ==
|
||||
dependencies:
|
||||
dicer "0.3.0"
|
||||
|
||||
busboy@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
||||
@ -4654,11 +4632,6 @@ clone-response@1.0.2:
|
||||
dependencies:
|
||||
mimic-response "^1.0.0"
|
||||
|
||||
clone@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
|
||||
integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
|
||||
|
||||
clone@^1.0.2:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||
@ -4685,16 +4658,6 @@ cluster-key-slot@^1.0.6:
|
||||
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
|
||||
integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==
|
||||
|
||||
co-body@6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.0.0.tgz#965b9337d7f5655480787471f4237664820827e3"
|
||||
integrity sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==
|
||||
dependencies:
|
||||
inflation "^2.0.0"
|
||||
qs "^6.5.2"
|
||||
raw-body "^2.3.3"
|
||||
type-is "^1.6.16"
|
||||
|
||||
co-body@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/co-body/-/co-body-4.2.0.tgz#74df20fa73262125dc45482af04e342ea8db3515"
|
||||
@ -7430,7 +7393,7 @@ flatted@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
|
||||
integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==
|
||||
|
||||
flatten@1.0.2, flatten@^1.0.2:
|
||||
flatten@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
|
||||
integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=
|
||||
@ -9417,11 +9380,6 @@ is-fullwidth-code-point@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-gen-fn@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-gen-fn/-/is-gen-fn-0.0.1.tgz#f276bf2a0083571abd01add47cd4da105a64ce13"
|
||||
integrity sha1-8na/KgCDVxq9Aa3UfNTaEFpkzhM=
|
||||
|
||||
is-generator-fn@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
|
||||
@ -10478,11 +10436,6 @@ kareem@2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.0.tgz#ef33c42e9024dce511eeaf440cd684f3af1fc769"
|
||||
integrity sha512-6hHxsp9e6zQU8nXsP+02HGWXwTkOEw6IROhF2ZA28cYbUk4eJ6QbtZvdqZOdD9YPKghG3apk5eOCvs+tLl3lRg==
|
||||
|
||||
kcors@^2.2.0:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/kcors/-/kcors-2.2.2.tgz#b6250e7a4f0a33c8f477b7fd0dfa11a3f3ca518d"
|
||||
integrity sha512-rIqbKa2S0gT0wC/790jsQM6hNpABHBNWQ7+XYS1xJV6zOGxlanW+RtCmlDn6wPZsGpRk371yy8abfBgl2OTavg==
|
||||
|
||||
keygrip@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.3.tgz#399d709f0aed2bab0a059e0cdd3a5023a053e1dc"
|
||||
@ -10668,23 +10621,6 @@ koa-is-json@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14"
|
||||
integrity sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=
|
||||
|
||||
koa-joi-router@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-joi-router/-/koa-joi-router-6.0.0.tgz#072ad3bfefb31b161166dfd70e567a0d86e24848"
|
||||
integrity sha512-h2KSH4HfVr02wGi+AR8OIRZlJRoAzJ/6f/CXaU06EjLK3zuB2ftOw7SAhTzL7Fjsu1aM4u9EM5FtTxv984c0bg==
|
||||
dependencies:
|
||||
"@hapi/joi" "15.0.0"
|
||||
await-busboy "1.0.3"
|
||||
clone "2.1.2"
|
||||
co-body "6.0.0"
|
||||
debug "4.1.1"
|
||||
delegates "1.0.0"
|
||||
flatten "1.0.2"
|
||||
is-gen-fn "0.0.1"
|
||||
koa-router "7.4.0"
|
||||
methods "1.1.2"
|
||||
sliced "1.0.1"
|
||||
|
||||
koa-locale@~1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-locale/-/koa-locale-1.3.0.tgz#95289ae6fa4098804a1ee8aadd46b0af1c82cbcb"
|
||||
@ -10707,7 +10643,7 @@ koa-qs@^2.0.0:
|
||||
merge-descriptors "~0.0.2"
|
||||
qs "~2.3.3"
|
||||
|
||||
koa-router@7.4.0, koa-router@^7.4.0:
|
||||
koa-router@^7.4.0:
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-router/-/koa-router-7.4.0.tgz#aee1f7adc02d5cb31d7d67465c9eacc825e8c5e0"
|
||||
integrity sha512-IWhaDXeAnfDBEpWS6hkGdZ1ablgr6Q6pGdXCyK38RbzuH4LkUOpPqPw+3f8l8aTDrQmBQ7xJc0bs2yV4dzcO+g==
|
||||
@ -11705,7 +11641,7 @@ merge2@^1.2.3:
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5"
|
||||
integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==
|
||||
|
||||
methods@1.1.2, methods@^1.0.1, methods@~1.1.2:
|
||||
methods@^1.0.1, methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
|
||||
@ -14924,7 +14860,7 @@ raw-body@2.4.0:
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
raw-body@^2.2.0, raw-body@^2.3.3:
|
||||
raw-body@^2.2.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c"
|
||||
integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user