wallet-svr/src/api.server.ts
2022-10-18 15:00:38 +08:00

178 lines
4.7 KiB
TypeScript

import fastify, {
FastifyError,
FastifyInstance,
FastifyReply,
FastifyRequest,
} from "fastify";
import helmet from "@fastify/helmet";
import { IncomingMessage, Server, ServerResponse } from "http";
import { RouterMap } from "decorators/router";
import { mongoose } from "@typegoose/typegoose";
import logger from "logger/logger";
import config from "config/config";
const zReqParserPlugin = require("plugins/zReqParser");
const zTokenParserPlugin = require("plugins/zTokenParser");
const apiAuthPlugin = require("plugins/apiauth");
const fs = require("fs");
const join = require("path").join;
require("./common/Extend");
export class ApiServer {
server: FastifyInstance<Server, IncomingMessage, ServerResponse>;
public constructor() {
this.server = fastify({ logger: true, trustProxy: true });
this.registerPlugins();
}
private registerPlugins() {
this.server.register(require("@fastify/formbody"));
this.server.register(zReqParserPlugin);
this.server.register(helmet, { hidePoweredBy: false });
this.server.register(zTokenParserPlugin);
this.server.register(apiAuthPlugin, {
secret: config.api.token_secret,
expiresIn: config.api.token_expiresIn,
});
this.server.register(require("@fastify/cors"), {});
}
private registerRouter() {
logger.log("register api routers");
let self = this;
for (let [controller, config] of RouterMap.decoratedRouters) {
for (let data of config.data) {
logger.info(
"add router",
data.method || "all",
data.path,
`${data.target.constructor.name}.${controller.name}()`
);
// @ts-ignore
self.server[data.method || "all"](
data.path,
{
preValidation: async function (
request: FastifyRequest,
reply: FastifyReply
) {
request.roles = config.roles;
await this.apiAuth(request, reply);
},
},
controller
);
}
}
}
/**
* 加载所有的controller
*/
initControllers() {
logger.info("Bootstrap controllers...");
const controllers = join(__dirname, "./controllers");
fs.readdirSync(controllers)
.filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/))
.forEach((file: any) => {
// logger.log(file);
return require(join(controllers, file));
});
}
async connectDB() {
const options = {
useNewUrlParser: true,
poolSize: 5,
keepAlive: true,
keepAliveInitialDelay: 300000,
useUnifiedTopology: true,
};
const uri = config.db_main;
logger.info(`connect to ${uri} ...`);
try {
// await mongoose.createConnection(uri, options)
await mongoose.connect(uri, options);
logger.log("DB Connected");
} catch (err) {
logger.log(`DB Connection Error: ${err.message}`);
}
}
private setErrHandler() {
this.server.setNotFoundHandler(function (
request: any,
reply: { send: (arg0: { errcode: number; errmsg: string }) => void }
) {
reply.send({ errcode: 404, errmsg: "page not found" });
});
this.server.setErrorHandler(function (
error: FastifyError,
request: FastifyRequest,
reply: FastifyReply
) {
let statusCode = (error && error.statusCode) || 100;
if (statusCode >= 500) {
logger.error(error);
} else if (statusCode >= 400) {
logger.info(error);
} else {
logger.error(error);
}
reply.code(200).send({
errcode: statusCode,
errmsg: error ? error.message : "unknown error",
});
});
}
/**
* 格式化接口返回数据, 统一封装成如下格式
* {
* code: 0,
* msg?: '',
* data: any
* }
* @private
*/
private setFormatSend() {
this.server.addHook(
"preSerialization",
async (request: FastifyRequest, reply: FastifyReply, payload) => {
reply.header("X-Powered-By", "PHP/5.4.16");
// @ts-ignore
if (!payload.errcode) {
payload = {
errcode: 0,
data: payload,
};
}
return payload;
}
);
}
public async start() {
let self = this;
return new Promise(async (resolve, reject) => {
await self.connectDB();
self.initControllers();
self.registerRouter();
self.setErrHandler();
self.setFormatSend();
// new Schedule().start();
this.server.listen(
{ port: config.api.port },
(err: any, address: any) => {
if (err) {
logger.log(err);
process.exit(0);
}
resolve && resolve(address);
}
);
});
}
}