Install
npm i egg-bag-framework
Built-in multiple modules, middleware and tools
Source code address ,
demo address
middleware
Verify whether the Sing signature is legal to prevent arbitrary requests
'use strict' ;
module . exports = ( option, app ) => {
return async function sing ( ctx, next ) {
const sing = ctx. request . header . sing ;
const { domain, expireTime, cache } = ctx. app . config . website ;
const default_cache = 'redis' ;
if (sing) {
let getSing = null ;
if (cache === default_cache) {
getSing = await app. redis . get (sing);
} else {
getSing = await app. lru . get (sing);
}
if (getSing) {
ctx. body = ctx. resultData ({ msg : 'sing signature has expired' }); // Expired if present
} else {
try {
const decSing = ctx. helper . aesDecrypt (sing);
const singData = JSON . parse (decSing);
if (singData. domain === domain) {
if (cache === default_cache) {
await app. redis . set (sing, 1 );
} else {
await app. lru . set (sing, 1 );
}
await app. redis . set (sing, 1 );
await app. redis . expire (sing, expireTime);
await next ();
} else {
ctx. body = ctx. resultData ({ msg : 'Sing signature is illegal, missing string' });
}
} catch (e) {
ctx. body = ctx. resultData ({ msg : 'sing signature is illegal' });
}
}
} else {
ctx.body = ctx.resultData ({ msg : ' Missing sing signature' }) ;
}
};
};
Current limiting middleware
Prevent the interface from being maliciously stolen. If it is attacked, request to use nginx or server configuration white and blacklist
'use strict' ;
const { RateLimiterMemory } = require ( 'rate-limiter-flexible' ); // Rate limiting middleware
module . exports = () => {
// Create a memory-based token bucket rate limiter, Limit 12 requests per second
const opts = {
points : 12 ,
duration : 1 ,
};
const rateLimiter = new RateLimiterMemory (opts);
return async function limiter ( ctx, next ) {
rateLimiter.consume ( ctx.request.ip )
. then ( rateLimiterRes => {
next ();
})
.catch ( rateLimiterRes = > {
ctx. body = ctx. resultData ({ msg : 'Current limiting triggered' , code : 2001 });
});
};
};
Verifyjwt
'use strict' ;
module . exports = () => {
return async function authority ( ctx, next ) {
const authorization = ctx. request . header . authorization ;
if (authorization) {
try {
ctx. helper . verifyToken (authorization); // Verify jwt
await next ();
} catch (err) {
ctx. body = ctx. resultData ({ msg : 'access_token expired' , code : 1003 });
}
} else {
ctx. body = ctx. resultData ({ msg : 'missing access_token' , code : 1003 });
}
};
};
Built-in module
jwt
(JWT) is an open standard (RFC 7519) that defines a compact, self-contained way to securely transmit information between parties as JSON objects. This information can be verified and trusted because it is digitally signed
// plugin.js
exports . jwt = {
enable : true ,
package : 'egg-jwt' ,
};
// config.default.js
config. jwt = {
secret : 'ABCD20231017QWERYSUNXSJL' , // You can customize
the sign : {
expiresIn : 8 * 60 * 60 , // Expiration time is 8 hours
},
};
Validate
Parameter verification module
// plugin.js
exports . validate = {
enable : true ,
package : 'egg-validate' ,
};
// config.default.js
config. validate = {
convert : true ,
translate () {
const args = Array . prototype . slice . call ( arguments );
return I18n. __ . apply (I18n, args);
},
};
redis
Redis is an open source (BSD licensed), in-memory data structure server that can be used as a database, cache, and message queue broker
// plugin.js
exports . redis = {
enable : true ,
package : 'egg-redis' ,
};
// config.default.js
config. redis = {
client : {
port : 6379 ,
host : '127.0.0.1' ,
password : 'auth' ,
db : 0 ,
},
}
lru
local cache
exports . lru = {
enable : true ,
package : 'egg-lru' , // local cache
};
config. lru = {
client : {
max : 3000 , // All lru cache configurations are available
maxAge : 1000 * 60 * 30 , // 60 min cache
},
app : true , // Loaded into the app, the default is open
agent : false , // Loaded into the agent, the default is closed
};
Upload mode
// config.default.js
config. multipart = {
mode : 'file' ,
fileSize : '50mb' , // Receive file size
whitelist : [ // Allowed file types to be received
'.png' ,
'.jpg' ,
' .webp' ,
'.gif' ,
'.zip' ,
'.doc' ,
'.docx' ,
'.txt' ,
'.xlsx' ,
'.pdf' ,
'.mp4' ,
'.webm' ,
' .mov' ,
'.flv' ,
'.avi' ,
'.f4v' ,
'.mov' ,
'.m4v' ,
'.rmvb' ,
'.rm' ,
'.mpg' ,
'.mpeg' ,
],
};
Sequelize
Sequelize is a promise-based Node.js ORM that currently supports Postgres , MySQL , MariaDB , SQLite and Microsoft SQL Server . It has powerful transaction support, relationships, pre-reading and delayed loading, read replication and other functions
// plugin.js
exports . sequelize = {
enable : true ,
package : 'egg-sequelize' ,
};
config. sequelize = {
dialect : 'mysql' ,
database : 'pm_webleading' ,
host : '127.0.0.1' ,
port : '3306' ,
username : 'pm_webleading' ,
password : '123456' ,
underscored : false ,
timezone : ' +08:00' ,
define : {
timestamps : true ,
freezeTableName : true ,
},
};
Mysql
MySQL is the most popular relational database management system. In terms of WEB applications, MySQL is one of the best RDBMS (Relational Database Management System) application software.
// plugin.js
exports . mysql = {
enable : true ,
package : 'egg-mysql' ,
};
// config.default.js
config. mysql = {
client : {
// host
host : '127.0.0.1' ,
// port number
port : '3306' ,
// username
user : 'pm_webleading' ,
// password
password : '123456' ,
// Database name
database : 'pm_webleading' ,
},
// Whether to load on the app,
the app will be enabled by default : true ,
// Whether to load on the agent,
the agent will be disabled by default : false ,
};
Built-in tools
The method called on the egg.js and ctx objects is as follows
'use strict' ;
const { Controller } = require ( 'egg' );
class HomeController extends Controller {
async index () {
const {ctx} = this ;
try {
for ( const file of ctx. request . files ) {
const filePath = await ctx. helper . uploadLocaFile ({file}) // cxt.helper.xxxx
}
} finally {
await ctx. cleanupRequestFiles ();
}
}
}
module . exports = HomeController ;
Upload files locally
Files of the above configuration types can be uploaded
uploadLocaFile ( { file, filePath } ) {
const { ctx } = this ;
return new Promise ( async (resolve, reject) => {
try {
const filename = file. filename ;
const extname = path. extname (filename);
const _filePath = filePath || `public/upload/ ${ctx.helper.nanoid()} ${extname} ` ;
const localPath = path. join (ctx. app . baseDir , 'app' , _filePath);
// Read the file
const source = fs. createReadStream (file. filepath );
// Create a write stream
const target = fs. createWriteStream (localPath);
await pump (source, target);
resolve (_filePath);
} catch (err) {
reject (err);
}
});
}
Upload images – with compression
Only pictures can be uploaded
uploadLocalImage ( { file, filePath, width = 500 , quality = 75 } ) {
const { ctx } = this ;
const extname = path. extname (file. filename );
const _filePath = filePath || `public/image/ ${ctx .helper.nanoid()} ${extname} ` ;
const localPath = path. join (ctx. app . baseDir , 'app' , _filePath);
return new Promise ( ( resolve, reject ) => {
Jimp . read (file . filepath )
. then ( image => {
image. resize (width, Jimp . AUTO )
. quality (quality)
.write (localPath);
resolve ( _filePath);
})
.catch ( err => {
reject (err) ;
});
});
}
Symmetric encryption
aesEncrypt ( data, options ) {
options = Object . assign ({ key : this . app . config . website . key , iv : this . app . config . website . iv }, options);
let str = data;
if ( typeof data === 'object' ) {
str = JSON . stringify (data);
}
str = CryptoJS . enc . Utf8 . parse (str);
const crypto = CryptoJS . AES . encrypt (str, CryptoJS . enc . Utf8 . parse (options. key ), {
iv : CryptoJS . enc . Utf8 . parse (options. iv ),
mode : CryptoJS . mode . ECB ,
padding : CryptoJS . pad . Pkcs7 ,
});
return crypto. toString (); // Symmetric encryption content
},
Symmetric decryption
aesDecrypt ( data, options ) {
options = Object . assign ({ key : this . app . config . website . key , iv : this . app . config . website . iv }, options);
const decrypt = CryptoJS . AES . decrypt (data, CryptoJS . enc . Utf8 . parse (options. key ), {
iv : CryptoJS . enc . Utf8 . parse (options. iv ),
mode : CryptoJS . mode . ECB ,
padding : CryptoJS . pad . Pkcs7 ,
});
return CryptoJS . enc . Utf8 . stringify (decrypt); // Symmetrically decrypted content
},
asymmetric encryption
encrypt ( str, options ) {
options = Object . assign ({ publicKey : this . app . config . website . publicKey }, options);
const encrypted = new JSEncrypt ();
encrypted. setPublicKey (options. publicKey . toString ());
return encrypted. encrypt (str); // Asymmetric encrypted string
},
Asymmetric decryption
decrypt ( str, options ) {
options = Object . assign ({ privateKey : this . app . config . website . privateKey }, options);
const decrypted = new JSEncrypt (); // Create a decryption object instance
decrypted. setPrivateKey (options. privateKey . toString ()); // Set the private key
return decrypted. decrypt (str); // Asymmetric decryption content
},
md5 encryption
md5 ( data ) {
let str = data;
if ( typeof data === 'object' ) {
str = JSON . stringify (data);
}
return CryptoJS . MD5 (str)
.toString ( );
},
Random ID
nanoid ( size = 12 ) {
const nanoid = customAlphabet (alphabet. join ( '' ), size);
if (size >= 12 ) {
return dayjs ()
. format ( 'YYYYMMDD' ) + nanoid (); // Get a unique random ID
}
return nanoid (); // Get repeated random ID
},
jwt-generate token-verify token
generateToken ( data ) {
return this . app . jwt . sign (data, this . app . config . jwt . secret ); // Generate token
},
verifyToken ( token ) {
return this . app . jwt . verify (token, this . app . config . jwt . secret ); // Verify token
},
