178 lines
4.7 KiB
TypeScript
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);
|
|
}
|
|
);
|
|
});
|
|
}
|
|
}
|