mirror of
https://github.com/chillzhuang/Sword
synced 2024-11-23 18:59:27 +08:00
116 lines
2.8 KiB
JavaScript
116 lines
2.8 KiB
JavaScript
|
const pathToRegexp = require('path-to-regexp');
|
||
|
const bodyParser = require('body-parser');
|
||
|
|
||
|
const mockFile = require('./mock/index');
|
||
|
|
||
|
const BODY_PARSED_METHODS = ['post', 'put', 'patch'];
|
||
|
|
||
|
const debug = console.log;
|
||
|
function parseKey(key) {
|
||
|
let method = 'get';
|
||
|
let path = key;
|
||
|
if (key.indexOf(' ') > -1) {
|
||
|
const splited = key.split(' ');
|
||
|
method = splited[0].toLowerCase();
|
||
|
path = splited[1]; // eslint-disable-line
|
||
|
}
|
||
|
return {
|
||
|
method,
|
||
|
path,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function createHandler(method, path, handler) {
|
||
|
return (req, res, next) => {
|
||
|
function sendData() {
|
||
|
if (typeof handler === 'function') {
|
||
|
handler(req, res, next);
|
||
|
} else {
|
||
|
res.json(handler);
|
||
|
}
|
||
|
}
|
||
|
if (BODY_PARSED_METHODS.includes(method)) {
|
||
|
bodyParser.json({ limit: '5mb', strict: false })(req, res, () => {
|
||
|
bodyParser.urlencoded({ limit: '5mb', extended: true })(req, res, () => {
|
||
|
sendData();
|
||
|
});
|
||
|
});
|
||
|
} else {
|
||
|
sendData();
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function normalizeConfig(config) {
|
||
|
return Object.keys(config).reduce((memo, key) => {
|
||
|
const handler = config[key];
|
||
|
const { method, path } = parseKey(key);
|
||
|
const keys = [];
|
||
|
const re = pathToRegexp(path, keys);
|
||
|
memo.push({
|
||
|
method,
|
||
|
path,
|
||
|
re,
|
||
|
keys,
|
||
|
handler: createHandler(method, path, handler),
|
||
|
});
|
||
|
return memo;
|
||
|
}, []);
|
||
|
}
|
||
|
|
||
|
const mockData = normalizeConfig(mockFile);
|
||
|
|
||
|
function matchMock(req) {
|
||
|
const { path: exceptPath } = req;
|
||
|
const exceptMethod = req.method.toLowerCase();
|
||
|
function decodeParam(val) {
|
||
|
if (typeof val !== 'string' || val.length === 0) {
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
return decodeURIComponent(val);
|
||
|
} catch (err) {
|
||
|
if (err instanceof URIError) {
|
||
|
err.message = `Failed to decode param ' ${val} '`;
|
||
|
err.statusCode = 400;
|
||
|
err.status = 400;
|
||
|
}
|
||
|
|
||
|
throw err;
|
||
|
}
|
||
|
}
|
||
|
// eslint-disable-next-line no-restricted-syntax
|
||
|
for (const mock of mockData) {
|
||
|
const { method, re, keys } = mock;
|
||
|
if (method === exceptMethod) {
|
||
|
const match = re.exec(req.path);
|
||
|
if (match) {
|
||
|
const params = {};
|
||
|
|
||
|
for (let i = 1; i < match.length; i += 1) {
|
||
|
const key = keys[i - 1];
|
||
|
const prop = key.name;
|
||
|
const val = decodeParam(match[i]);
|
||
|
|
||
|
if (val !== undefined || !hasOwnProperty.call(params, prop)) {
|
||
|
params[prop] = val;
|
||
|
}
|
||
|
}
|
||
|
req.params = params;
|
||
|
return mock;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return mockData.filter(({ method, re }) => method === exceptMethod && re.test(exceptPath))[0];
|
||
|
}
|
||
|
module.exports = (req, res, next) => {
|
||
|
const match = matchMock(req);
|
||
|
if (match) {
|
||
|
debug(`mock matched: [${match.method}] ${match.path}`);
|
||
|
return match.handler(req, res, next);
|
||
|
}
|
||
|
return next();
|
||
|
};
|