Commit 83927e18 authored by 温海元's avatar 温海元

Initial commit

parents
Pipeline #892 failed with stages
module.exports = {
"extends": "airbnb-base"
};
\ No newline at end of file
/node_modules
/logs
package-lock.json
\ No newline at end of file
# ${ip}:3333/testdata/getall?count=2
\ No newline at end of file
const Koa = require('koa');
const path = require('path');
const cors = require('kcors');
const log4js = require('koa-log4');
const favicon = require('koa-favicon');
const controller = require('./app/controller');
// const Middles = require('./middleware');
global.config = require('./config/app.conf');
const { config } = global;
const faviconPath = path.resolve(__dirname, './public/favicon.ico');
const logFormat = ':remote-addr - - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent" :response-time ms';
const app = new Koa();
const logDir = path.join(__dirname, 'logs');
log4js.configure(config.log4js.conf, { cwd: logDir });
app.use(favicon(faviconPath))
.use(log4js.koaLogger(log4js.getLogger('http'), { level: 'auto', format: logFormat }))
.use(cors({
maxAge: 86400, // options请求缓存24小时
origin(req) {
return req.header.origin;
},
}))
// .use(Middles.router(app, { root: './app/controller' }))
.use(controller());
app.listen(3333);
const fs = require('fs');
const Router = require('koa-router');
const router = new Router();
const log4js = require('koa-log4');
const logger = log4js.getLogger('router');
// 解析规则 {'GET /': homepage}
function addRule(_router, rule) {
Object.keys(rule).forEach((key) => {
// key = 'GET /' rule = {'GET /': homepage}
if (key.startsWith('GET ')) {
const path = key.substring(4);
_router.get(path, rule[key]);
logger.info(`register URL mapping: GET ${path}`);
} else if (key.startsWith('POST ')) {
const path = key.substring(5);
_router.post(path, rule[key]);
logger.info(`register URL mapping: POST ${path}`);
} else {
logger.info(`invalid URL: ${key}`);
}
});
}
// 自动导入controller文件夹下所有的路由规则
function addRules(_router) {
// 得到 /controller 所有以js结尾的文件
const files = fs.readdirSync(`${__dirname}/controller`);
const jsFiles = files.filter(f => f.endsWith('.js'));
// 添加规则
jsFiles.forEach((jsFile) => {
// console.log(`process controller: ${f}...`);
logger.info(`process controller: ${jsFile}...`);
const rule = require(`${__dirname}/controller/${jsFile}`);
addRule(_router, rule);
});
}
module.exports = () => {
addRules(router);
return router.routes();
};
const bankID = require('../services/bankID');
const IDCard = require('../services/IDCard');
const mobile = require('../services/mobile');
// const createNameService = require('../services/CreateNameService')
const address = require('../services/address');
const name = require('../services/name');
const email = require('../services/email');
exports.createBankID = async () => {
const req = this.query;
let { bank } = req;
bank = bank ? bank.toUpperCase() : bankID.randomBank();
this.body = { code: '0000', bank: bankID.RandomCreateBankID(bank) };
};
// 获取银行列表
exports.getBankList = async function () {
this.body = bankID.bankList();
};
// 生成随机手机号
exports.getMoble = async function () {
this.body = { mobile: mobile.getMoble() };
};
// 生成地址
exports.getAddress = async function () {
const { province } = this.query;
this.body = { address: address.fullAddress(province) };
};
// 生成名字
exports.getName = async function () {
this.body = { name: name.getName() };
};
// 生成电子邮箱
exports.getEmail = async function () {
this.body = { email: email.email() };
};
exports.getID = async function () {
this.body = { IDCardNo: IDCard.RandomCreateID() };
};
exports.getAll = async function () {
const { province, bank } = this.query;
const count = this.query.count || 1;
const re = [];
for (let i = 0; i < count; i += 1) {
const ID = IDCard.RandomCreateID(province);
const item = {
name: name.getName(),
IDCardNo: ID,
sex: IDCard.getSex(ID),
birthday: IDCard.getBirthday(ID),
address: address.fullAddress(province),
mobile: mobile.getMoble(),
email: email.email(),
};
Object.assign(item, bankID.RandomCreateBankID(bank));
re.push(item);
}
this.body = { code: '0000', data: re };
};
const bankID = require('../services/bankID');
const IDCard = require('../services/IDCard');
const mobile = require('../services/mobile');
const address = require('../services/address');
const name = require('../services/name');
const email = require('../services/email');
const checkService = require('../services/checkService');
// 生成银行卡
async function getBankID(ctx) {
let { bank } = ctx.query;
bank = bank ? bank.toUpperCase() : bankID.randomBank();
ctx.body = { code: '0000', data: [bankID.RandomCreateBankID(bank)] };
}
// 获取银行列表
const getBankList = async (ctx) => {
ctx.body = { code: '0000', data: bankID.bankList() };
};
async function getProvinceList(ctx) {
ctx.body = { code: '0000', data: address.allProvince() };
}
async function getCountyList(ctx) {
ctx.body = address.allCounty();
}
// 生成随机手机号
async function getMoble(ctx) {
ctx.body = { mobile: mobile.getMoble() };
}
// 生成地址
async function getAddress(ctx) {
ctx.body = { address: address.address() };
}
// 生成名字
async function getName(ctx) {
ctx.body = { name: name.getName() };
}
// 生成电子邮箱
async function getEmail(ctx) {
ctx.body = { email: email.email() };
}
// 生成身份证
async function getID(ctx) {
const province = ctx.query.province || address.province();
const city = address.city(province);
const county = address.county(province, city);
ctx.body = {
IDCardNo: IDCard.randomCreateID(county.code),
province,
city,
county: county.name,
};
}
// 生成所有
async function getAll(ctx) {
const { bank } = ctx.query;
const count = ctx.query.count || 1;
const re = [];
for (let i = 0; i < count; i += 1) {
const province = ctx.query.province ? address.allProvince()
.filter(item => item.indexOf(ctx.query.province) !== -1)[0] : address.province();
const city = address.city(province);
const county = address.county(province, city);
const fullAddress = province + city + county.name;
const ID = IDCard.randomCreateID(county.code);
const item = {
name: name.getName(),
IDCardNo: ID,
sex: IDCard.getSex(ID),
birthday: IDCard.getBirthday(ID),
address: fullAddress + address.streetAddress(),
mobile: mobile.getMoble(),
email: email.email(),
};
Object.assign(item, bankID.RandomCreateBankID(bank));
re.push(item);
}
ctx.body = { code: '0000', count: re.length, data: re };
}
async function checkID(ctx) {
const ID = ctx.query.id || ctx.query.ID;
ctx.body = { data: checkService.ParseID(ID) };
}
async function chekBankCardID(ctx) {
const ID = ctx.query.id || ctx.query.ID;
ctx.body = { data: checkService.luhnCheck(ID) };
}
module.exports = {
'GET /testdata/getID': getID,
'GET /testdata/getAll': getAll,
'GET /testdata/getEmail': getEmail,
'GET /testdata/getName': getName,
'GET /testdata/getAddress': getAddress,
'GET /testdata/getBankID': getBankID,
'GET /testdata/getMoble': getMoble,
'GET /testdata/getBankList': getBankList,
'GET /testdata/getProvinceList': getProvinceList,
'GET /testdata/getCountyList': getCountyList,
'GET /testdata/checkID': checkID,
'GET /testdata/chekBankCardID': chekBankCardID,
};
// const checkService = require('./checkService')
const _ = require('lodash');
const address = require('./address');
// 根据15位身份证或者18位身份证的前17位生成18位身份证号码
function getCheckID(_pid) {
const arrVerifyCode = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
const wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
if (_pid.length !== 15 && _pid.length !== 17) return (false);
let ai = (_pid.length === 17) ? _pid : `${_pid.substr(0, 6)}19${_pid.substr(6)}`;
if (!/^\d+$/.test(ai)) {
return (false);
}
const yyyy = parseInt(ai.substr(6, 4), 10);
const mm = parseInt(ai.substr(10, 2) - 1, 10);
const dd = parseInt(ai.substr(12, 2), 10);
const d = new Date(yyyy, mm, dd); const year = d.getFullYear();
const mon = d.getMonth(); const day = d.getDate(); const now = new Date();
if (year !== yyyy || mon !== mm || day !== dd || d > now || now.getFullYear() - year > 140) {
return (false);
}
let ret = 0;
for (let i = 0; i < 17; i += 1) {
ret += ai.charAt(i) * wi[i];
}
ai += arrVerifyCode[ret %= 11];
return (ai);
}
// 随机生成一个身份证
function randomCreateID(_countyCode) {
let ff = false;
const countyCode = parseInt(_countyCode, 10) && _countyCode.length === 12
? _countyCode.substr(0, 6) : address.county().code.substr(0, 6);
while (!ff) {
let yyyy = 0; let mm = 0; let dd = 0; let rnd = 0;
yyyy = _.random(1960, 1990); mm = _.random(1, 12); dd = _.random(1, 31);
rnd = `${_.random(0, 9)}${_.random(0, 9)}${_.random(0, 9)}`;
if ((mm === 2) && (dd > 28)) {
dd = _.random(1, 28);
}
if (((mm === 4) || (mm === 6) || (mm === 9) || (mm === 11)) && (dd === 31)) {
dd -= 1;
}
mm = (mm < 10) ? (`0${mm}`) : mm;
dd = (dd < 10) ? (`0${dd}`) : dd;
const re = `${countyCode}${yyyy}${mm}${dd}${rnd}`;
ff = getCheckID(re);
}
return ff;
}
function getBirthday(_id) {
// let _id = checkService.ParseID(pid);
const id = `${_id}`;
if (id.length < 17) return 0;
const birthday = (new Date(id.substr(6, 4), id.substr(10, 2) - 1, id.substr(12, 2)))
.toLocaleDateString();
return birthday;
}
function getSex(_id) {
// let _id = checkService.ParseID(pid);
const id = _id.toString();
if (id.length < 17) return 0;
const sex = _id.substr(16, 1) % 2 ? '' : '';
return sex;
}
module.exports = {
randomCreateID,
getBirthday,
getSex,
};
const _ = require('lodash');
const random = require('./random');
const helpers = require('./helpers');
const allData = require('./mockz').data;
// 全部数据
const allCounty = () => allData;
// 全部省份
const allProvince = () => allData.map(item => item.name);
// 省级
const province = () => {
const idx = _.random(allData.length - 1);
return allData[idx].name;
};
// 市级
const city = (provName) => {
const pArr = _.filter(allData, { name: provName });
let prov;
if (pArr.length > 0) {
[prov] = pArr;
} else {
const pidx = _.random(allData.length - 1);
prov = allData[pidx];
}
const cidx = _.random(prov.children.length - 1);
return prov.children[cidx].name;
};
// 县级
const county = (provName, cityName) => {
const pidx = _.random(allData.length - 1);
let prov = allData[pidx];
const pArr = _.filter(allData, { name: provName });
if (pArr.length > 0) {
[prov] = pArr;
}
const cidx = _.random(prov.children.length - 1);
let ct = prov.children[cidx];
const cArr = _.filter(prov.children, { name: cityName });
if (cArr.length > 0) {
[ct] = cArr;
}
const idx = _.random(ct.children.length - 1);
return ct.children[idx];
};
function secondaryAddress() {
return helpers.replaceSymbolWithNumber(random.array_element(
[
'##栋#0#屋',
'##号楼#门#0#',
'#排#0#室',
],
));
}
function streetName() {
let result;
switch (random.number(2)) {
case 0:
result = random.first_name() + random.street_suffix();
break;
case 1:
result = `${random.first_name().substr(1, 1)}${random.last_name().substr(0, 1)}${random.street_suffix()}`;
break;
default:
}
return result;
}
function streetAddress() {
let address = '';
switch (random.number(3)) {
case 0:
address = `${streetName() + helpers.replaceSymbolWithNumber('###')}${random.last_name()}${random.last_name()}小区`;
break;
case 1:
address = `${streetName() + helpers.replaceSymbolWithNumber('##')}${random.first_name()}苑`;
break;
default:
address = `${streetName() + helpers.replaceSymbolWithNumber('#')}号院`;
break;
}
return address + secondaryAddress();
}
// 地址
const address = () => {
const pidx = _.random(allData.length - 1);
const prov = allData[pidx];
const cidx = _.random(prov.children.length - 1);
const ct = prov.children[cidx];
const cyidx = _.random(ct.children.length - 1);
const cy = ct.children[cyidx];
return `${prov.name}${ct.name}${cy.name}${streetAddress()}`;
};
module.exports = {
address,
province,
city,
county,
streetAddress,
allProvince,
allCounty,
};
const checkService = require('./checkService');
const banklist = require('./definitions').cn_bank;
const bankList = () => banklist;
const randomBank = () => banklist[Math.floor(Math.random() * banklist.length)];
// 随机生成一个卡号
const RandomCreateBankID = (_bankType) => {
const bankTypeName = _bankType ? banklist
.filter(item => item.indexOf(_bankType) !== -1)[0] : randomBank();
const [, bankType] = bankTypeName.split(' ');
let bankNo = '';
let flag = true;
while (flag) {
const cardPrefix = [];
if (
bankType === 'ICBC'
|| bankType === 'CCB'
|| bankType === 'ABC'
|| bankType === 'PSBC'
|| bankType === 'BCOM'
|| bankType === 'GDB'
|| bankType === 'BOC'
) {
for (let j = 0; j < 13; j += 1) {
cardPrefix.push(parseInt(Math.random() * 10, 10));
}
} else {
for (let j = 0; j < 10; j += 1) {
cardPrefix.push(parseInt(Math.random() * 10, 10));
}
}
const cardPrefixs = cardPrefix.join('');
switch (bankType) {
case 'CCB':
bankNo = `621700${cardPrefixs}`;
break;
case 'CMBC':
bankNo = `621691${cardPrefixs}`;
break;
case 'ABC':
bankNo = `622827${cardPrefixs}`;
break;
case 'BCOM':
bankNo = `622262${cardPrefixs}`;
break;
case 'CMB':
bankNo = `621486${cardPrefixs}`;
break;
case 'SPDB':
bankNo = `622521${cardPrefixs}`;
break;
case 'GDB':
bankNo = `622568${cardPrefixs}`;
break;
case 'HXB':
bankNo = `622632${cardPrefixs}`;
break;
// case 'PAB':
// bankNo = `622298${cardPrefixs}`;
// break;
case 'CITIC':
bankNo = `622696${cardPrefixs}`;
break;
case 'ICBC':
bankNo = `620058${cardPrefixs}`;
break;
case 'BOC':
bankNo = `620061${cardPrefixs}`;
break;
case 'CIB':
bankNo = `622908${cardPrefixs}`;
break;
case 'CEB':
bankNo = `622660${cardPrefixs}`;
break;
case 'PSBC':
bankNo = `621799${cardPrefixs}`;
break;
default:
bankNo = `621700${cardPrefixs}`;
}
if (checkService.luhnCheck(bankNo)) {
flag = false;
}
}
return { bankType: bankTypeName, bankNo };
};
module.exports = {
RandomCreateBankID,
bankList,
randomBank,
};
// 判断输入的15位或者18位身份证号码是否合法
function ParseID(pId) {
const arrVerifyCode = [1, 0, 'x', 9, 8, 7, 6, 5, 4, 3, 2];
const wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
if (pId.length !== 15 && pId.length !== 18) {
return ('身份证号码只能是15位或18位!');
}
let ai = (pId.length === 18) ? pId.substr(0, 17) : `${pId.substr(0, 6)}19${pId.substr(6)}`;
if (!/^\d+$/.test(ai)) {
return ('身份证除最后一位外,必须为数字!');
}
const yyyy = ai.substr(6, 4);
const mm = ai.substr(10, 2) - 1;
const dd = ai.substr(12, 2);
const d = new Date(yyyy, mm, dd);
const year = d.getFullYear();
const mon = d.getMonth();
const day = d.getDate();
const now = new Date();
if (year != yyyy || mon != mm || day != dd || d > now || now.getFullYear() - year > 140) {
return ('身份证出生年月日输入错误!');
}
let ret = 0;
for (let i = 0; i < 17; i += 1) {
ret += ai.charAt(i) * wi[i];
}
ai += arrVerifyCode[ret %= 11];
return ((pId.length === 18 && pId.toLowerCase() !== ai) ? `身份证输入错误,正确的为\n${ai}!` : ai);
}
// luhn校验规则:16位银行卡号(19位通用):
// 1.将未带校验位的 15(或18)位卡号从右依次编号 1 到 15(18),位于奇数位号上的数字乘以 2。
// 2.将奇位乘积的个十位全部相加,再加上所有偶数位上的数字。
// 3.将加法和加上校验位能被 10 整除。
function luhnCheck(_bankNo) {
const bankNo = `${_bankNo}`;
if (!(bankNo.length === 16 || bankNo.length === 19)) {
return `卡号位数不正确:${_bankNo}`;
}
// 取出最后一位(与luhn进行比较)
const lastNum = bankNo.substr(bankNo.length - 1, 1);
// 前15或18位
const first15Num = bankNo.substr(0, bankNo.length - 1);
const newArr = [];
// 前15或18位倒序存进数组
for (let i = first15Num.length - 1; i > -1; i -= 1) {
newArr.push(parseInt(first15Num.substr(i, 1), 10));
}
// 奇数位*2的积 <9
const arrJiShu = [];
// 奇数位*2的积 >9
const arrJiShu2 = [];
// 偶数位数组
const arrOuShu = [];
for (let i = 0; i < newArr.length; i += 1) {
if ((i + 1) % 2 === 1) {
if (newArr[i] * 2 < 9) {
arrJiShu.push(newArr[i] * 2);
} else {
arrJiShu2.push(newArr[i] * 2);
}
} else {
arrOuShu.push(newArr[i]);
}
}
// 奇数位*2 >9 的分割之后的数组个位数
const jishuChildOne = [];
// 奇数位*2 >9 的分割之后的数组十位数
const jishuChileTwo = [];
arrJiShu2.forEach((item) => {
jishuChildOne.push(item % 10);
jishuChileTwo.push(parseInt(item / 10, 10));
});
// 奇数位*2 < 9 的数组之和
const sumJiShu = arrJiShu.reduce((x, y) => x + y, 0);
// 偶数位数组之和
const sumOuShu = arrOuShu.reduce((x, y) => x + y, 0);
// 奇数位*2 >9 的分割之后的数组个位数之和
const sumJiShuChild1 = jishuChildOne.reduce((x, y) => x + y, 0);
// 奇数位*2 >9 的分割之后的数组十位数之和
const sumJiShuChild2 = jishuChileTwo.reduce((x, y) => x + y, 0);
// 计算总和
const sumTotal = sumJiShu + sumOuShu + sumJiShuChild1 + sumJiShuChild2;
// 计算luhn值
const k = sumTotal % 10 === 0 ? 10 : sumTotal % 10;
const luhn = `${10 - k}`;
if (lastNum === luhn) {
return true;
}
return false;
}
module.exports = {
ParseID,
luhnCheck,
};
const randomHz = () => {
eval('var word=' + '"\\u' + (Math.round(Math.random() * 20901) + 19968).toString(16) + '"');
return word;
};
const getName = () => {
const familyNames = ['', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '',
'欧阳', '太史', '端木', '上官', '司马', '东方', '独孤', '南宫', '万俟', '闻人', '夏侯', '诸葛', '尉迟',
'公羊', '赫连', '澹台', '皇甫', '宗政', '濮阳', '公冶', '太叔', '申屠', '公孙', '慕容', '仲孙',
'钟离', '长孙', '宇文', '司徒', '鲜于', '司空', '闾丘', '子车', '亓官', '司寇', '巫马', '公西',
'颛孙', '壤驷', '公良', '漆雕', '乐正', '宰父', '谷梁', '拓跋', '夹谷', '轩辕', '令狐', '段干',
'百里', '呼延', '东郭', '南门', '羊舌', '微生', '公户', '公玉', '公仪', '梁丘', '公仲', '公上',
'公门', '公山', '公坚', '左丘', '公伯', '西门', '公祖', '第五', '公乘', '贯丘', '公皙', '南荣',
'东里', '东宫', '仲长', '子书', '子桑', '即墨', '达奚', '褚师', '吴铭'];
const givenNames = ['子璇', '', '国栋', '夫子', '瑞堂', '', '', '', '国贤', '贺祥', '晨涛',
'昊轩', '易轩', '益辰', '益帆', '益冉', '瑾春', '瑾昆', '春齐', '', '文昊',
'东东', '雄霖', '浩晨', '熙涵', '溶溶', '冰枫', '欣欣', '宜豪', '欣慧', '建政',
'美欣', '淑慧', '文轩', '文杰', '欣源', '忠林', '榕润', '欣汝', '慧嘉', '新建',
'建林', '亦菲', '', '冰洁', '佳欣', '涵涵', '禹辰', '淳美', '泽惠', '伟洋',
'涵越', '润丽', '', '淑华', '晶莹', '凌晶', '苒溪', '雨涵', '嘉怡', '佳毅',
'子辰', '佳琪', '紫轩', '瑞辰', '昕蕊', '', '明远', '欣宜', '泽远', '欣怡',
'佳怡', '佳惠', '晨茜', '晨璐', '运昊', '汝鑫', '淑君', '晶滢', '润莎', '榕汕',
'佳钰', '佳玉', '晓庆', '一鸣', '语晨', '添池', '添昊', '雨泽', '雅晗', '雅涵',
'清妍', '诗悦', '嘉乐', '晨涵', '天赫', '玥傲', '佳昊', '天昊', '萌萌', '若萌'];
const i = parseInt(Math.floor(Math.random() * familyNames.length), 10);
const familyName = familyNames[i];
const j = parseInt(Math.floor(Math.random() * givenNames.length), 10);
const givenName = givenNames[j] + randomHz();
// let givenName = randomHz() + randomHz()
const name = familyName + givenName;
return name;
};
module.exports = {
getName,
};
This diff is collapsed.
const Random = require('./random');
const Helpers = require('./helpers');
const getEmail = {
email() {
return `${Helpers.slugify(this.userName())}@${Helpers.slugify(this.domainName())}`;
},
userName() {
let result;
switch (Random.number(2)) {
case 0:
result = Random.first_name();
break;
default:
result = Random.first_name() + Random.array_element(['.', '_']) + Random.last_name();
break;
}
return result;
},
domainName() {
return `${this.domainWord()}.${Random.domain_suffix()}`;
},
domainWord() {
return Random.first_name().toLowerCase();
},
ip() {
const randNum = () => (Math.random() * 254 + 1).toFixed(0);
const result = [];
for (let i = 0; i < 4; i += 1) {
result[i] = randNum();
}
return result.join('.');
},
};
module.exports = getEmail;
const pinyin = require('pinyin');
const _ = require('lodash');
// parses string for a symbol and replace it with a random number from 1-10
exports.replaceSymbolWithNumber = (string, _symbol) => {
// default symbol is '#'
const symbol = _symbol || '#';
return string.split('').map((item) => {
if (item === symbol) {
return _.random(1, 9);
}
return item;
}).join('');
};
// slugifies string
exports.slugify = string => pinyin(string)
.join('')
.toLowerCase()
.replace(/ /g, '-')
.replace(/[^\w.-]+/g, '');
module.exports.getMoble = () => {
const prefixArray = ['130', '131', '132', '133', '135', '137', '138', '170', '187', '189'];
let prefix = prefixArray[parseInt(prefixArray.length * Math.random(), 10)];
for (let j = 0; j < 8; j += 1) {
prefix += Math.floor(Math.random() * 10);
}
return prefix;
};
This diff is collapsed.
const Random = require('./random');
const name = {
firstName() {
return Random.first_name();
},
lastName() {
return Random.last_name();
},
getName() {
return this.lastName() + this.firstName();
},
};
module.exports = name;
const definitions = require('./definitions');
const random = {
// returns a single random number based on a range
number(range) {
return Math.floor(Math.random() * range);
},
// 生成一定范围的随机数
randomBy(under, over) {
switch (arguments.length) {
case 1:
return parseInt(Math.random() * under + 1, 10);
case 2:
return parseInt(Math.random() * (over - under + 1) + under, 10);
default:
return 0;
}
},
// takes an array and returns the array randomly sorted
array_element(array) {
const r = Math.floor(Math.random() * array.length);
return array[r];
},
city_prefix() {
return this.array_element(definitions.city_prefix);
},
city_suffix() {
return this.array_element(definitions.city_suffix);
},
street_suffix() {
return this.array_element(definitions.street_suffix);
},
br_state() {
return this.array_element(definitions.br_state);
},
br_state_abbr() {
return this.array_element(definitions.br_state_abbr);
},
cn_state() {
return this.array_element(definitions.cn_state);
},
cn_city(filter) {
return this.array_element(definitions.cn_city.filter(item => item.indexOf(filter || '') !== -1));
},
cn_state_abbr() {
return this.array_element(definitions.cn_state_abbr);
},
uk_county() {
return this.array_element(definitions.uk_county);
},
uk_country() {
return this.array_element(definitions.uk_country);
},
first_name() {
return this.array_element(definitions.first_name);
},
last_name() {
return this.array_element(definitions.last_name);
},
name_prefix() {
return this.array_element(definitions.name_prefix);
},
name_suffix() {
return this.array_element(definitions.name_suffix);
},
catch_phrase_adjective() {
return this.array_element(definitions.catch_phrase_adjective);
},
catch_phrase_descriptor() {
return this.array_element(definitions.catch_phrase_descriptor);
},
catch_phrase_noun() {
return this.array_element(definitions.catch_phrase_noun);
},
bs_adjective() {
return this.array_element(definitions.bs_adjective);
},
bs_buzz() {
return this.array_element(definitions.bs_buzz);
},
bs_noun() {
return this.array_element(definitions.bs_noun);
},
phone_formats() {
return this.array_element(definitions.phone_formats);
},
domain_suffix() {
return this.array_element(definitions.domain_suffix);
},
};
module.exports = random;
const path = require('path');
const logPath = path.resolve(__dirname, '../logs');
// const layout = { type: 'pattern', pattern: '%d{yyyy-MM-dd hh:mm:ss.SSS} %p %c %m%n' };
module.exports = {
log4js: {
path: logPath,
conf: {
appenders: {
default: { type: 'console' },
file: {
type: 'dateFile',
filename: `${logPath}/sys-api.log`,
pattern: '.yyyy-MM-dd',
keepFileExt: true,
},
},
categories: {
default: { appenders: ['default', 'file'], level: 'info' },
file: { appenders: ['file'], level: 'info' },
},
},
},
};
'use strict';
const fs = require('fs');
const curPath = __dirname;
fs.readdirSync(curPath).forEach((item) => {
let filePath = `${curPath}/${item}/index.js`;
if (fs.existsSync(filePath)) {
exports[item] = require(filePath)
}
})
'use strict';
import path from 'path'
import http from 'http'
import Koa from 'koa'
import router from '../index'
const app = new Koa()
app.use(router(app, {
root: path.resolve(__dirname, './controller'),
default_path: '/index',
default_jump: true,
domain: '127.0.0.1',
errorPath: '/error/404'
}))
module.exports = http.createServer(app.callback());
module.exports = function*() {
function getData() {
return function(callback) {
setTimeout(function() {
callback(0, { data: 'this is defaultCtrl!' });
}, 100)
}
}
return yield getData();
}
exports['404'] = function* () {
this.body = '这是自定义的404页';
}
\ No newline at end of file
exports.generator = function*() {
this.body = 'hello world!';
}
exports.await = async function() {
this.body = 'hello world!';
}
exports.bindDefault = function*(argument) {
let result = yield this.bindDefault();
this.body = result.data;
}
exports.param = async function() {
this.body = this.params;
}
exports.param.__regular__ = '/:id1/:id2'
exports.post = function() {
this.body = 'hello world!';
}
exports.post.__method__ = 'post'
exports.test1 = {
aj_1: function() {
this.body = this.request.url;
},
aj_2: {
aj_2_1: function() {
this.body = this.request.url;
},
aj_2_2: function() {
this.body = this.request.url;
}
},
aj_3: {
aj_3_1: {
// 该路由层级超过三级,生成路由失败
aj_3_1_1: function() {
this.body = this.request.url;
}
}
}
}
exports.test2 = function*() {
this.body = this.request.url;
}
exports.test3 = function*() {
this.body = this.request.url;
}
exports.index = function*() {
this.body = this.request.url;
}
exports.index = function*() {
this.body = 'hello world!';
}
exports.index.__controller__ = false;
\ No newline at end of file
exports.index = function* () {
this.body = this.request.url;
}
exports.order = function* () {
this.body = this.request.url;
}
\ No newline at end of file
'use strict';
require("babel-register")({
"presets": ["es2015-node5"],
"plugins": [
"transform-async-to-generator",
"syntax-async-functions"
]
});
const app = require('./app');
app.listen(3001)
'use strict';
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
const router = require('./lib/router');
const debug = require('debug')('koa-grace:router');
const error = require('debug')('koa-grace-error:router');
/**
* [_routerVerb 可以注册的方法]
* all = ['acl', 'bind', 'checkout', 'connect', 'copy', 'delete', 'get', 'head', 'link', 'lock', 'm-search', 'merge', 'mkactivity', 'mkcalendar', 'mkcol', 'move', 'notify', 'options', 'patch', 'post', 'propfind', 'proppatch', 'purge', 'put', 'rebind', 'report', 'search', 'subscribe', 'trace', 'unbind', 'unlink', 'unlock', 'unsubscribe' ]
* @all {会注册33个verb, 慎用!!!}
* delete {作为保留词,推荐使用别称:del}
*/
const _routerVerb = ['get', 'post', 'put', 'patch', 'del', 'head', 'delete', 'all', 'options'];
/**
* 生成路由控制
* @param {string} app context
* @param {object} options 配置项
* {string} options.root controller路径
* {string} options.defualt_jump 如果访问路径为纯域名是否做跳转,默认为false
* {string} options.default_path 默认路径
* {string} options.domain 请求域名,可不传
* @return {function}
*
* @todo lib/router.js this.MATCHS 中如果配置的规则路由特别多,内存溢出的风险
*/
module.exports = function graceRouter(app, options) {
if (typeof options === 'string') {
options = { root: options }
} else if (!options || !options.root) {
throw new Error('`root` config required.');
}
const Router = router(options);
const Domain = options.domain || '';
// app的默认路由
if (options.default_jump !== false && options.default_path) {
Router.redirect('/', options.default_path);
}
let root = options.root;
// 如果root不存在则直接跳过
if (!fs.existsSync(root)) {
error('error : can\'t find route path ' + root);
return function* ctrl(next) { yield next; };
}
_ls(root).forEach((filePath) => {
if (!/([a-zA-Z0-9_\-]+)(\.js)$/.test(filePath)) {
return;
}
try {
var exportFuncs = require(filePath);
} catch (err) {
console.error(`error: require ${filePath} error ${err}`);
return;
}
let pathRegexp = _formatPath(filePath, root);
getRoute(exportFuncs, (exportFun, ctrlpath) => {
_setRoute(Router, {
domain: Domain,
method: exportFun.__method__,
regular: exportFun.__regular__,
ctrlpath: ctrlpath,
ctrl: exportFun
}, options);
}, [pathRegexp]);
});
// 添加bindDefault方法
// 如果defaultCtrl文件存在则注入,否则忽略
let defaultCtrlRoot = options.defaultCtrlRoot || options.root;
let defaultCtrlPath = path.resolve(defaultCtrlRoot, 'defaultCtrl.js')
app.context.__defineGetter__("bindDefault", () => {
try {
return require(defaultCtrlPath);
} catch (err) {
return new Promise((resolve) => {
error(`Cannot find default controller '${defaultCtrlPath}'`)
resolve();
})
}
});
return async function graceRouter(ctx, next) {
await Router.routes()(ctx, next);
await next();
}
}
/**
* 递归生成路由,层级不超过3级
* @param {Object|Function} exportFuncs 获取到的路由
* @param {Array} ctrlpath 路由记录
* @return
*/
function getRoute(exportFuncs, cb, ctrlpath, curCtrlname) {
ctrlpath = ctrlpath || [];
// 如果当前设置了不是路由,则直接返回
if (exportFuncs.__controller__ === false) {
return;
}
let totalCtrlname = curCtrlname ? ctrlpath.concat([curCtrlname]) : ctrlpath;
// 只允许3级路由层级
if (ctrlpath.length > 3) {
debug(`嵌套路由对象层级不能超过3级:${totalCtrlname.join('/')}`);
return;
}
// 如果是一个方法就直接执行cb
if (typeof exportFuncs === 'function') {
cb(exportFuncs, totalCtrlname);
} else {
// 否则进行循环递归查询
for (let ctrlname in exportFuncs) {
if (!exportFuncs.hasOwnProperty(ctrlname)) {
continue
}
getRoute(exportFuncs[ctrlname], cb, totalCtrlname, ctrlname);
}
}
}
/**
* 查找目录中的所有文件
* @param {string} dir 查找路径
* @param {init} _pending 递归参数,忽略
* @param {array} _result 递归参数,忽略
* @return {array} 文件list
*/
function _ls(dir, _pending, _result) {
_pending = _pending ? _pending++ : 1;
_result = _result || [];
if (!path.isAbsolute(dir)) {
dir = path.join(process.cwd(), dir);
}
// if error, throw it
let stat = fs.lstatSync(dir);
if (stat.isDirectory()) {
let files = fs.readdirSync(dir);
files.forEach(function (part) {
_ls(path.join(dir, part), _pending, _result);
});
if (--_pending === 0) {
return _result;
}
} else {
_result.push(dir);
if (--_pending === 0) {
return _result;
}
}
}
/**
* 格式化文件路径为koa-router的path
* @param {string} filePath 文件路径
* @param {string} root router路径
* @return {string} 过滤之后的path
*/
function _formatPath(filePath, root) {
let dir = root;
if (!path.isAbsolute(root)) {
dir = path.join(process.cwd(), root);
}
// 修复windows下的\路径问题
dir = dir.replace(/\\/g, '/');
return filePath
.replace(/\\/g, '/')
.replace(dir, '')
.split('.')[0];
}
/**
* 设置路由
* @param {string} path 当前文件路径
* @param {object} config 配置项
* {string} config.method 当前请求方法:get,post等
* {string} config.regular 参考:https://github.com/alexmingoia/koa-router#nested-routers
* {string} config.ctrlname 当前controller名称
* {funtion} config.ctrl controller方法
* @param {Obejct} options grace router配置
*/
function _setRoute(Router, config, options) {
let paths = [];
// let method = config.method || 'get';
// let method = (_routerVerb.indexOf(config.method) > -1) ? [config.method] : ['get', 'post'];
let method = _.isArray(config.method) ? config.method :
(_routerVerb.indexOf(config.method) > -1) ? [config.method] : ['get'];
let ctrlpath = config.ctrlpath.join('/');
// 加入当前路由
paths.push(ctrlpath)
// 如果当前路由配置方案为不跳转,则设置路由'/'为options.default_path路由
if (options.default_jump === false && ctrlpath == options.default_path) {
paths.push('/');
}
// 如果当前路由是以index结尾,则把其父路由也加入路由
if (config.ctrlpath.slice(-1)[0] === 'index') {
let parpath = config.ctrlpath.slice(0, -1);
paths.push(parpath.join('/'));
}
// 如果有regular则加入regular路由
if (config.regular) {
paths.push(ctrlpath + config.regular);
}
// 对每一个method,有定义时唯一,默认post/get
method.forEach((_method) => {
// 注入路由
paths.forEach((pathItem) => {
debug(_method + ':' + config.domain + pathItem);
Router[_method](pathItem, config.ctrl);
});
});
}
var debug = require('debug')('koa-router');
var pathToRegExp = require('path-to-regexp');
module.exports = Layer;
/**
* Initialize a new routing Layer with given `method`, `path`, and `middleware`.
*
* @param {String|RegExp} path Path string or regular expression.
* @param {Array} methods Array of HTTP verbs.
* @param {Array} middleware Layer callback/middleware or series of.
* @param {Object=} opts
* @param {String=} opts.name route name
* @param {String=} opts.sensitive case sensitive (default: false)
* @param {String=} opts.strict require the trailing slash (default: false)
* @returns {Layer}
* @private
*/
function Layer(path, methods, middleware, opts) {
this.opts = opts || {};
this.name = this.opts.name || null;
this.methods = [];
this.paramNames = [];
this.stack = Array.isArray(middleware) ? middleware : [middleware];
methods.forEach(function(method) {
var l = this.methods.push(method.toUpperCase());
if (this.methods[l-1] === 'GET') {
this.methods.unshift('HEAD');
}
}, this);
// ensure middleware is a function
this.stack.forEach(function(fn) {
var type = (typeof fn);
if (type !== 'function') {
throw new Error(
methods.toString() + " `" + (this.opts.name || path) +"`: `middleware` "
+ "must be a function, not `" + type + "`"
);
}
}, this);
this.path = path;
this.regexp = pathToRegExp(path, this.paramNames, this.opts);
debug('defined route %s %s', this.methods, this.opts.prefix + this.path);
};
/**
* Returns whether request `path` matches route.
*
* @param {String} path
* @returns {Boolean}
* @private
*/
Layer.prototype.match = function (path) {
return this.regexp.test(path);
};
/**
* Returns map of URL parameters for given `path` and `paramNames`.
*
* @param {String} path
* @param {Array.<String>} captures
* @param {Object=} existingParams
* @returns {Object}
* @private
*/
Layer.prototype.params = function (path, captures, existingParams) {
var params = existingParams || {};
for (var len = captures.length, i=0; i<len; i++) {
if (this.paramNames[i]) {
var c = captures[i];
params[this.paramNames[i].name] = c ? safeDecodeURIComponent(c) : c;
}
}
return params;
};
/**
* Returns array of regexp url path captures.
*
* @param {String} path
* @returns {Array.<String>}
* @private
*/
Layer.prototype.captures = function (path) {
return path.match(this.regexp).slice(1);
};
/**
* Generate URL for route using given `params`.
*
* @example
*
* ```javascript
* var route = new Layer(['GET'], '/users/:id', fn);
*
* route.url({ id: 123 }); // => "/users/123"
* ```
*
* @param {Object} params url parameters
* @returns {String}
* @private
*/
Layer.prototype.url = function (params) {
var args = params;
var url = this.path;
var toPath = pathToRegExp.compile(url);
// argument is of form { key: val }
if (typeof params != 'object') {
args = Array.prototype.slice.call(arguments);
}
if (args instanceof Array) {
var tokens = pathToRegExp.parse(url);
var replace = {};
for (var len = tokens.length, i=0, j=0; i<len; i++) {
if (tokens[i].name) replace[tokens[i].name] = args[j++];
}
return toPath(replace);
}
else {
return toPath(params);
}
};
/**
* Run validations on route named parameters.
*
* @example
*
* ```javascript
* router
* .param('user', function *(id, next) {
* this.user = users[id];
* if (!user) return this.status = 404;
* yield next;
* })
* .get('/users/:user', function *(next) {
* this.body = this.user;
* });
* ```
*
* @param {String} param
* @param {Function} middleware
* @returns {Layer}
* @private
*/
Layer.prototype.param = function (param, fn) {
var stack = this.stack;
var params = this.paramNames;
var middleware = function *(next) {
next = fn.call(this, this.params[param], next);
if (typeof next.next === 'function') {
yield *next;
} else {
yield Promise.resolve(next);
}
};
middleware.param = param;
params.forEach(function (p, i) {
var prev = params[i - 1];
if (param === p.name) {
// insert param middleware in order params appear in path
if (prev) {
if (!stack.some(function (m, i) {
if (m.param === prev.name) {
return stack.splice(i, 0, middleware);
}
})) {
stack.some(function (m, i) {
if (!m.param) {
return stack.splice(i, 0, middleware);
}
});
}
} else {
stack.unshift(middleware);
}
}
});
return this;
};
/**
* Prefix route path.
*
* @param {String} prefix
* @returns {Layer}
* @private
*/
Layer.prototype.setPrefix = function (prefix) {
if (this.path) {
this.path = prefix + this.path;
this.paramNames = [];
this.regexp = pathToRegExp(this.path, this.paramNames, this.opts);
}
return this;
};
/**
* Safe decodeURIComponent, won't throw any error.
* If `decodeURIComponent` error happen, just return the original value.
*
* @param {String} text
* @returns {String} URL decode original string.
* @private
*/
function safeDecodeURIComponent(text) {
try {
return decodeURIComponent(text);
} catch (e) {
return text;
}
}
This diff is collapsed.
{
"name": "testdata-koa",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "./node_modules/.bin/nodemon app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"kcors": "^2.2.2",
"koa": "^2.5.2",
"koa-favicon": "^2.0.1",
"koa-log4": "^2.3.0",
"koa-router": "^7.4.0",
"lodash": "^4.17.10",
"methods": "^1.1.2",
"path-to-regexp": "^2.4.0",
"pinyin": "^2.8.3"
},
"devDependencies": {
"eslint": "^5.5.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.14.0",
"nodemon": "^1.18.4"
}
}
#!/bin/sh
source /etc/profile
pm2 start app.js --node-args="--harmony" -n testdata
\ No newline at end of file
#!/bin/sh
source /etc/profile
pm2 stop testdata
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment