增加一些基本的代码
This commit is contained in:
parent
51947d4b73
commit
8f9c5e3f64
18
docs/api.md
18
docs/api.md
@ -1,6 +1,8 @@
|
||||
# 卡牌游戏接口说明
|
||||
## 一. 说明
|
||||
|
||||
所有接口均需上传sessionid
|
||||
|
||||
通用返回JSON结构, 接口Response的数据结构说明只包含data部分
|
||||
``` JSON
|
||||
{
|
||||
@ -14,7 +16,7 @@
|
||||
## 二. 客户端接口列表
|
||||
|
||||
### 1. 玩家资料
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid/uinfo
|
||||
|
||||
| 字段 | 说明 |
|
||||
@ -28,7 +30,7 @@
|
||||
```
|
||||
|
||||
### 2. 可用卡牌信息
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid/cards
|
||||
|
||||
| 字段 | 说明 |
|
||||
@ -52,7 +54,7 @@
|
||||
```
|
||||
|
||||
### 3. 可用英雄列表
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid
|
||||
|
||||
| 字段 | 说明 |
|
||||
@ -80,7 +82,7 @@
|
||||
```
|
||||
|
||||
### 4. 自定义卡组列表
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid/card_group/:heroid
|
||||
|
||||
| 字段 | 说明 |
|
||||
@ -128,7 +130,7 @@
|
||||
根据errcode判断成功or失败
|
||||
|
||||
### 6. 删除卡组
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid/card_group/delete/:gid
|
||||
|
||||
|
||||
@ -165,7 +167,7 @@
|
||||
根据errcode判断成功or失败
|
||||
|
||||
### 8. 抽卡
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid/card/draw/:count
|
||||
|
||||
| 字段 | 说明 |
|
||||
@ -186,7 +188,7 @@
|
||||
```
|
||||
|
||||
### 9. 对战记录列表
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid/records
|
||||
|
||||
| 字段 | 说明 |
|
||||
@ -221,7 +223,7 @@
|
||||
```json
|
||||
{
|
||||
exp: 1022, // 当前经验值
|
||||
exp_get: 100, // 本次获得的经验
|
||||
exp_POST: 100, // 本次获得的经验
|
||||
level: 1 // 当前等级
|
||||
}
|
||||
```
|
||||
|
43
package-lock.json
generated
43
package-lock.json
generated
@ -29,6 +29,7 @@
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz",
|
||||
"integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@ -51,6 +52,7 @@
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.3.tgz",
|
||||
"integrity": "sha512-6YNqGP1hk5bjUFaim+QoFFuI61WjHiHE1BNeB41TA00Xd2K7zG4lcWyLLq/XtIp36uMavvS5hoAUJ+1u/GcX2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/bson": "*",
|
||||
"@types/node": "*"
|
||||
@ -590,9 +592,9 @@
|
||||
}
|
||||
},
|
||||
"kareem": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
|
||||
"integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz",
|
||||
"integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw=="
|
||||
},
|
||||
"light-my-request": {
|
||||
"version": "4.4.1",
|
||||
@ -700,11 +702,11 @@
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz",
|
||||
"integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==",
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.1.tgz",
|
||||
"integrity": "sha512-uH76Zzr5wPptnjEKJRQnwTsomtFOU/kQEU8a9hKHr2M7y9qVk7Q4Pkv0EQVp88742z9+RwvsdTw6dRjDZCNu1g==",
|
||||
"requires": {
|
||||
"bl": "^2.2.1",
|
||||
"bl": "^2.2.0",
|
||||
"bson": "^1.1.4",
|
||||
"denque": "^1.4.1",
|
||||
"require_optional": "^1.0.1",
|
||||
@ -720,17 +722,16 @@
|
||||
}
|
||||
},
|
||||
"mongoose": {
|
||||
"version": "5.11.10",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.10.tgz",
|
||||
"integrity": "sha512-daE2L6VW7WNywv7tL2KUkBViWvODbzr50Of1kJpIbzW3w3N5/TYcgSmhCsEDWfYGQXbun2rdd7+sOdsEC8zQSQ==",
|
||||
"version": "5.10.3",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.10.3.tgz",
|
||||
"integrity": "sha512-FLemltuzcsCHlFpEZ3bYOiNhJfHful+GoS+3uRgdEWGlY0HKfOjm9xsISM/tql8vRvhjr7qveuRfoBBGO3xNtw==",
|
||||
"requires": {
|
||||
"@types/mongodb": "^3.5.27",
|
||||
"bson": "^1.1.4",
|
||||
"kareem": "2.3.2",
|
||||
"mongodb": "3.6.3",
|
||||
"kareem": "2.3.1",
|
||||
"mongodb": "3.6.1",
|
||||
"mongoose-legacy-pluralize": "1.0.2",
|
||||
"mpath": "0.8.3",
|
||||
"mquery": "3.2.3",
|
||||
"mpath": "0.7.0",
|
||||
"mquery": "3.2.2",
|
||||
"ms": "2.1.2",
|
||||
"regexp-clone": "1.0.0",
|
||||
"safe-buffer": "5.2.1",
|
||||
@ -756,14 +757,14 @@
|
||||
"integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
|
||||
},
|
||||
"mpath": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz",
|
||||
"integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA=="
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.7.0.tgz",
|
||||
"integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg=="
|
||||
},
|
||||
"mquery": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.3.tgz",
|
||||
"integrity": "sha512-cIfbP4TyMYX+SkaQ2MntD+F2XbqaBHUYWk3j+kqdDztPWok3tgyssOZxMHMtzbV1w9DaSlvEea0Iocuro41A4g==",
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz",
|
||||
"integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==",
|
||||
"requires": {
|
||||
"bluebird": "3.5.1",
|
||||
"debug": "3.1.0",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"dev:api": "DEBUG=colyseus:*,jc:* node --require ts-node/register --inspect src/api.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
@ -22,14 +22,14 @@
|
||||
"fastify-jwt": "^2.2.0",
|
||||
"fastify-plugin": "^3.0.0",
|
||||
"mime-types": "^2.1.28",
|
||||
"mongoose": "^5.11.10",
|
||||
"mongoose": "5.10.3",
|
||||
"mongoose-findorcreate": "^3.0.0",
|
||||
"tracer": "^1.1.4",
|
||||
"urlencode": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/debug": "^4.1.5",
|
||||
"@types/mongoose": "^5.10.3",
|
||||
"@types/debug": "4.1.5",
|
||||
"@types/mongoose": "5.10.3",
|
||||
"@types/node": "^14.14.20",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.3"
|
||||
|
@ -1,4 +1,9 @@
|
||||
import fastify, {FastifyError, FastifyInstance} from 'fastify'
|
||||
import fastify, {
|
||||
FastifyError,
|
||||
FastifyInstance,
|
||||
FastifyReply,
|
||||
FastifyRequest
|
||||
} from 'fastify'
|
||||
import helmet from 'fastify-helmet'
|
||||
import { Server, IncomingMessage, ServerResponse } from 'http'
|
||||
import {RouterMap} from './decorators/router';
|
||||
@ -7,7 +12,6 @@ import logger from './logger/logger';
|
||||
import {Config} from "./cfg/Config";
|
||||
|
||||
const zReqParserPlugin = require('./plugins/zReqParser');
|
||||
|
||||
const apiAuthPlugin = require('./plugins/apiauth');
|
||||
|
||||
const fs = require('fs');
|
||||
@ -25,10 +29,10 @@ export class ApiServer {
|
||||
private registerPlugins() {
|
||||
this.server.register(require('fastify-formbody'));
|
||||
this.server.register(zReqParserPlugin);
|
||||
// @ts-ignore
|
||||
this.server.register(apiAuthPlugin);
|
||||
this.server.register(
|
||||
helmet,
|
||||
{ hidePoweredBy: { setTo: 'PHP 4.2.0' } }
|
||||
{ hidePoweredBy: false }
|
||||
)
|
||||
|
||||
this.server.register(require('fastify-cors'), {});
|
||||
@ -57,7 +61,7 @@ export class ApiServer {
|
||||
*/
|
||||
initControllers() {
|
||||
logger.info('Bootstrap controllers...');
|
||||
const controllers = join(__dirname, 'api/controllers');
|
||||
const controllers = join(__dirname, 'controllers');
|
||||
fs.readdirSync(controllers)
|
||||
.filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/))
|
||||
.forEach((file: any) => {
|
||||
@ -81,10 +85,10 @@ export class ApiServer {
|
||||
}
|
||||
}
|
||||
private setErrHandler() {
|
||||
this.server.setNotFoundHandler(function(request: any, reply: { send: (arg0: { code: number; msg: string; }) => void; }){
|
||||
reply.send({code: 404, msg: 'page not found'})
|
||||
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: any, reply: { send: (arg0: { code: any; msg: any; }) => void; }) {
|
||||
this.server.setErrorHandler(function (error: FastifyError, request: any, reply: { send: (arg0: { errcode: any; errmsg: any; }) => void; }) {
|
||||
let statusCode = error && error.statusCode || 100;
|
||||
if (statusCode >= 500) {
|
||||
logger.error(error)
|
||||
@ -93,7 +97,19 @@ export class ApiServer {
|
||||
} else {
|
||||
logger.error(error)
|
||||
}
|
||||
reply.send({code: statusCode, msg: error ? error.message : 'unknown error'})
|
||||
reply.send({errcode: statusCode, errmsg: error ? error.message : 'unknown error'})
|
||||
})
|
||||
}
|
||||
private setFormatSend() {
|
||||
this.server.addHook('preSerialization', async (request: FastifyRequest, reply: FastifyReply, payload) => {
|
||||
// @ts-ignore
|
||||
if (!payload.errcode) {
|
||||
payload = {
|
||||
errcode: 0,
|
||||
data: payload
|
||||
}
|
||||
}
|
||||
return payload
|
||||
})
|
||||
}
|
||||
public async start() {
|
||||
@ -103,6 +119,7 @@ export class ApiServer {
|
||||
self.initControllers();
|
||||
self.registerRouter();
|
||||
self.setErrHandler();
|
||||
self.setFormatSend();
|
||||
this.server.listen({port: config.port}, (err: any, address: any) => {
|
||||
if (err) {
|
||||
logger.log(err)
|
||||
|
14
src/common/ZError.ts
Normal file
14
src/common/ZError.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {FastifyError} from "fastify";
|
||||
|
||||
export class ZError implements FastifyError {
|
||||
code: string;
|
||||
statusCode?: number;
|
||||
message: string;
|
||||
name: string;
|
||||
|
||||
|
||||
constructor(statusCode: number, message: string) {
|
||||
this.statusCode = statusCode;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
18
src/controllers/AccountController.ts
Normal file
18
src/controllers/AccountController.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import BaseController from "../common/base.controller";
|
||||
import {role, router} from "../decorators/router";
|
||||
import {Account} from "../models/Account";
|
||||
import {ZError} from "../common/ZError";
|
||||
|
||||
export default class AccountController extends BaseController {
|
||||
@role('anon')
|
||||
@router('post /api/:accountid/uinfo')
|
||||
async info(req: any, res: any) {
|
||||
let {accountid} = req.params;
|
||||
if (true) {
|
||||
throw new ZError(101, 'no acc');
|
||||
}
|
||||
let account = (await Account.findOrCreate({accountid})).doc;
|
||||
|
||||
return account.toJson();
|
||||
}
|
||||
}
|
35
src/models/Account.ts
Normal file
35
src/models/Account.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import {prop, getModelForClass, modelOptions, index, plugin} from '@typegoose/typegoose';
|
||||
import {dbconn} from '../decorators/dbconn';
|
||||
// @ts-ignore
|
||||
import findOrCreate from 'mongoose-findorcreate';
|
||||
import {Base, FindOrCreate, TimeStamps} from "@typegoose/typegoose/lib/defaultClasses";
|
||||
|
||||
interface AccountClass extends Base, TimeStamps {}
|
||||
@dbconn()
|
||||
@index({ accountid: 1}, { unique: true })
|
||||
@plugin(findOrCreate)
|
||||
@modelOptions({schemaOptions: {collection: "account", timestamps: true}})
|
||||
|
||||
class AccountClass extends FindOrCreate{
|
||||
@prop()
|
||||
public accountid: string;
|
||||
@prop()
|
||||
public city?: string;
|
||||
@prop({default: false})
|
||||
public locked: boolean;
|
||||
@prop()
|
||||
public lockedTime?: Date;
|
||||
@prop()
|
||||
public comment?: string;
|
||||
@prop()
|
||||
public lastLogin?: Date;
|
||||
|
||||
public toJson() {
|
||||
return {
|
||||
accountid: this.accountid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export const Account = getModelForClass(AccountClass, {existingConnection: AccountClass['db']});
|
60
src/plugins/apiauth.ts
Normal file
60
src/plugins/apiauth.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import {
|
||||
FastifyInstance,
|
||||
FastifyPluginAsync, FastifyReply,
|
||||
FastifyRequest,
|
||||
} from 'fastify';
|
||||
import fastifyPlugin from 'fastify-plugin';
|
||||
import {Account} from '../models/Account';
|
||||
|
||||
declare module 'fastify' {
|
||||
interface FastifyInstance {
|
||||
apiAuth: (request: FastifyRequest, reply: FastifyReply) => {};
|
||||
}
|
||||
|
||||
interface FastifyRequest {
|
||||
session?: {[key: string]: any};
|
||||
roles?: any,
|
||||
user?: any
|
||||
}
|
||||
}
|
||||
|
||||
const apiAuthPlugin: FastifyPluginAsync = async function(
|
||||
fastify: FastifyInstance,
|
||||
options?: any
|
||||
) {
|
||||
|
||||
// 只有路由配置的role为anon才不需要过滤
|
||||
fastify.decorate("apiAuth", async function(request: FastifyRequest, reply: FastifyReply) {
|
||||
if (!request.roles || request.roles.indexOf('anon') == -1) {
|
||||
try {
|
||||
// @ts-ignore
|
||||
let { accountid, sessionid } = request.params;
|
||||
//TODO: 增加sessionid的校验
|
||||
// if (!accountid || !sessionid) {
|
||||
// return reply.send({code: 11, msg: 'need accountid and sessionid'});
|
||||
// }
|
||||
if (!accountid) {
|
||||
return reply.send({code: 11, msg: 'need accountid and sessionid'});
|
||||
}
|
||||
// const data = this.jwt.verify(request.token);
|
||||
// if (!data || !data.id) {
|
||||
// return reply.send({code: 10, msg: 'need login'});
|
||||
// }
|
||||
// let account = await Account.findById(data.id);
|
||||
// if (!account) {
|
||||
// return reply.send({code: 10, msg: 'need login'});
|
||||
// }
|
||||
// request.user = account;
|
||||
|
||||
} catch (err) {
|
||||
return reply.send({code: 401, msg: 'need auth'})
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
export = fastifyPlugin(apiAuthPlugin, {
|
||||
fastify: '>=3.0.0',
|
||||
name: 'apiauth',
|
||||
});
|
41
src/plugins/zReqParser.ts
Normal file
41
src/plugins/zReqParser.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import {
|
||||
FastifyInstance,
|
||||
FastifyPluginAsync,
|
||||
FastifyReply,
|
||||
FastifyRequest
|
||||
} from "fastify";
|
||||
import fastifyPlugin from "fastify-plugin";
|
||||
|
||||
/**
|
||||
* 将post 和 get 的参数统一到 req.params
|
||||
*/
|
||||
declare module 'fastify' {
|
||||
interface FastifyInstance {
|
||||
zReqParser: (request: FastifyRequest, reply: FastifyReply) => {};
|
||||
}
|
||||
|
||||
interface FastifyRequest {
|
||||
session?: {[key: string]: any};
|
||||
}
|
||||
}
|
||||
const zReqParserPlugin: FastifyPluginAsync = async function(
|
||||
fastify: FastifyInstance,
|
||||
options?: any,
|
||||
) {
|
||||
fastify.addHook('preValidation', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let params = request.params || {};
|
||||
if (request.query) {
|
||||
Object.assign(params, request.query);
|
||||
}
|
||||
if (request.body) {
|
||||
Object.assign(params, request.body);
|
||||
}
|
||||
request.params = params;
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
export = fastifyPlugin(zReqParserPlugin, {
|
||||
fastify: '>=3.0.0',
|
||||
name: 'zReqParser',
|
||||
});
|
@ -15,6 +15,7 @@
|
||||
"strictNullChecks": false,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user