lrf 11 mēneši atpakaļ
revīzija
4c34a4544c

+ 11 - 0
.editorconfig

@@ -0,0 +1,11 @@
+# 🎨 editorconfig.org
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+insert_final_newline = true

+ 7 - 0
.eslintrc.json

@@ -0,0 +1,7 @@
+{
+  "extends": "./node_modules/mwts/",
+  "ignorePatterns": ["node_modules", "dist", "test", "jest.config.js", "typings"],
+  "env": {
+    "jest": true
+  }
+}

+ 13 - 0
.gitignore

@@ -0,0 +1,13 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+coverage/
+dist/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+.tsbuildinfo
+.tsbuildinfo.*

+ 3 - 0
.prettierrc.js

@@ -0,0 +1,3 @@
+module.exports = {
+  ...require('mwts/.prettierrc.json')
+}

+ 6 - 0
README.md

@@ -0,0 +1,6 @@
+# 未完成:
+  * [x] 1.代理请求
+  * [ ] 2.对数据进行解密
+	* [ ]	3.接口鉴权
+  * [ ] 4.i18n处理
+

+ 29 - 0
README.zh-CN.md

@@ -0,0 +1,29 @@
+# my_midway_project
+
+## 快速入门
+
+<!-- 在此次添加使用文档 -->
+
+如需进一步了解,参见 [midway 文档][midway]。
+
+### 本地开发
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### 部署
+
+```bash
+$ npm start
+```
+
+### 内置指令
+
+- 使用 `npm run lint` 来做代码风格检查。
+- 使用 `npm test` 来执行单元测试。
+
+
+[midway]: https://midwayjs.org

+ 2 - 0
bootstrap.js

@@ -0,0 +1,2 @@
+const { Bootstrap } = require('@midwayjs/bootstrap');
+Bootstrap.run();

+ 6 - 0
jest.config.js

@@ -0,0 +1,6 @@
+module.exports = {
+  preset: 'ts-jest',
+  testEnvironment: 'node',
+  testPathIgnorePatterns: ['<rootDir>/test/fixtures'],
+  coveragePathIgnorePatterns: ['<rootDir>/test/'],
+};

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 13477 - 0
package-lock.json


+ 49 - 0
package.json

@@ -0,0 +1,49 @@
+{
+  "name": "proxy",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "dependencies": {
+    "@midwayjs/axios": "^3.16.0",
+    "@midwayjs/bootstrap": "^3.12.0",
+    "@midwayjs/core": "^3.12.0",
+    "@midwayjs/i18n": "^3.16.1",
+    "@midwayjs/info": "^3.12.0",
+    "@midwayjs/jwt": "^3.16.1",
+    "@midwayjs/koa": "^3.12.0",
+    "@midwayjs/logger": "^3.1.0",
+    "@midwayjs/validate": "^3.12.0",
+    "lodash": "^4.17.21"
+  },
+  "devDependencies": {
+    "@midwayjs/mock": "^3.12.0",
+    "@types/jest": "^29.2.0",
+    "@types/lodash": "^4.17.1",
+    "@types/node": "14",
+    "cross-env": "^6.0.0",
+    "jest": "^29.2.2",
+    "mwts": "^1.3.0",
+    "mwtsc": "^1.4.0",
+    "ts-jest": "^29.0.3",
+    "typescript": "~4.8.0"
+  },
+  "engines": {
+    "node": ">=12.0.0"
+  },
+  "scripts": {
+    "start": "NODE_ENV=production node ./bootstrap.js",
+    "dev": "cross-env NODE_ENV=local mwtsc --watch --run @midwayjs/mock/app.js",
+    "test": "cross-env NODE_ENV=unittest jest",
+    "cov": "jest --coverage",
+    "lint": "mwts check",
+    "lint:fix": "mwts fix",
+    "ci": "npm run cov",
+    "build": "mwtsc --cleanOutDir"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "anonymous",
+  "license": "MIT"
+}

+ 9 - 0
src/config/config.default.ts

@@ -0,0 +1,9 @@
+import { MidwayConfig } from '@midwayjs/core';
+
+export default {
+  // use for cookie sign key, should change to your own and keep security
+  keys: '1715577385578_8567',
+  koa: {
+    port: 19700,
+  },
+} as MidwayConfig;

+ 20 - 0
src/config/config.local.ts

@@ -0,0 +1,20 @@
+import { MidwayConfig } from '@midwayjs/core';
+
+export default {
+  // use for cookie sign key, should change to your own and keep security
+  keys: '1715577385578_8567',
+  koa: {
+    port: 19700,
+  },
+  axios: {
+    clients: {
+      // key则为路由前缀
+      '/api': {
+        baseURL: 'http://127.0.0.1:9700',
+      },
+      '/test/api': {
+        baseURL: 'http://127.0.0.1:9701',
+      },
+    },
+  },
+} as MidwayConfig;

+ 7 - 0
src/config/config.unittest.ts

@@ -0,0 +1,7 @@
+import { MidwayConfig } from '@midwayjs/core';
+
+export default {
+  koa: {
+    port: null,
+  },
+} as MidwayConfig;

+ 28 - 0
src/configuration.ts

@@ -0,0 +1,28 @@
+import { Configuration, App } from '@midwayjs/core';
+import * as koa from '@midwayjs/koa';
+import * as validate from '@midwayjs/validate';
+import * as info from '@midwayjs/info';
+import { join } from 'path';
+import { ReportMiddleware } from './middleware/report.middleware';
+import * as axios from '@midwayjs/axios';
+@Configuration({
+  imports: [
+    koa,
+    axios,
+    validate,
+    {
+      component: info,
+      enabledEnvironment: ['local'],
+    },
+  ],
+  importConfigs: [join(__dirname, './config')],
+})
+export class MainConfiguration {
+  @App('koa')
+  app: koa.Application;
+
+  async onReady() {
+    // add middleware
+    this.app.useMiddleware([ReportMiddleware]);
+  }
+}

+ 23 - 0
src/controller/home.controller.ts

@@ -0,0 +1,23 @@
+import { All, Controller, Get, Inject } from '@midwayjs/core';
+import { Context } from '@midwayjs/koa';
+import { ProxyService } from '../service/proxy.service';
+@Controller('/')
+export class HomeController {
+  @Inject()
+  ctx: Context;
+
+  @Inject()
+  service: ProxyService;
+
+  @Get('/')
+  async home(): Promise<string> {
+    return 'proxy starting....';
+  }
+
+  @All('/**')
+  async proxy() {
+    const rb = this.service.getRequstBase();
+    return await this.service.toProxy();
+    // return 'in proxy';
+  }
+}

+ 13 - 0
src/filter/default.filter.ts

@@ -0,0 +1,13 @@
+import { Catch } from '@midwayjs/core';
+import { Context } from '@midwayjs/koa';
+
+@Catch()
+export class DefaultErrorFilter {
+  async catch(err: Error, ctx: Context) {
+    // 所有的未分类错误会到这里
+    return {
+      success: false,
+      message: err.message,
+    };
+  }
+}

+ 10 - 0
src/filter/notfound.filter.ts

@@ -0,0 +1,10 @@
+import { Catch, httpError, MidwayHttpError } from '@midwayjs/core';
+import { Context } from '@midwayjs/koa';
+
+@Catch(httpError.NotFoundError)
+export class NotFoundFilter {
+  async catch(err: MidwayHttpError, ctx: Context) {
+    // 404 错误会到这里
+    ctx.redirect('/404.html');
+  }
+}

+ 6 - 0
src/interface.ts

@@ -0,0 +1,6 @@
+/**
+ * @description User-Service parameters
+ */
+export interface IUserOptions {
+  uid: number;
+}

+ 12 - 0
src/interface/proxy.interface.ts

@@ -0,0 +1,12 @@
+export interface RequestBase {
+  method: string;
+  header: object;
+  originalUrl: string;
+  path: string;
+  query?: object;
+  querystring?: string;
+  body?: object;
+  rawBody?: string;
+  host: string;
+  ip?: string;
+}

+ 27 - 0
src/middleware/report.middleware.ts

@@ -0,0 +1,27 @@
+import { Middleware, IMiddleware } from '@midwayjs/core';
+import { NextFunction, Context } from '@midwayjs/koa';
+
+@Middleware()
+export class ReportMiddleware implements IMiddleware<Context, NextFunction> {
+  resolve() {
+    return async (ctx: Context, next: NextFunction) => {
+      // 控制器前执行的逻辑
+      const startTime = Date.now();
+      // 执行下一个 Web 中间件,最后执行到控制器
+      // 这里可以拿到下一个中间件或者控制器的返回值
+      const result = await next();
+      // 控制器之后执行的逻辑
+      ctx.logger.info(
+        `Report in "src/middleware/report.middleware.ts", rt = ${
+          Date.now() - startTime
+        }ms`
+      );
+      // 返回给上一个中间件的结果
+      return result;
+    };
+  }
+
+  static getName(): string {
+    return 'report';
+  }
+}

+ 78 - 0
src/service/proxy.service.ts

@@ -0,0 +1,78 @@
+import { Config, Inject, InjectClient, Provide } from '@midwayjs/core';
+import { Context } from '@midwayjs/koa';
+import { RequestBase } from '../interface/proxy.interface';
+import { get, lowerCase, pick } from 'lodash';
+import { HttpServiceFactory, HttpService } from '@midwayjs/axios';
+import { Axios } from '@midwayjs/axios';
+@Provide()
+export class ProxyService {
+  @Inject()
+  ctx: Context;
+
+  @Config('axios.clients')
+  axiosClients: object;
+
+  @InjectClient(HttpServiceFactory, 'default')
+  serviceAxios: HttpService;
+
+  @Inject()
+  sf: HttpServiceFactory;
+
+  getRequstBase(): RequestBase {
+    const request = this.ctx.request;
+    const result: RequestBase = pick(request, [
+      'method',
+      'header',
+      'path',
+      'query',
+      'querystring',
+      'body',
+      'rawBody',
+      'host',
+      'ip',
+      'originalUrl',
+    ]) as RequestBase;
+
+    return result;
+  }
+
+  async toProxy() {
+    const rb: RequestBase = this.getRequstBase();
+    // 解析路由前缀
+    const uri = rb.originalUrl;
+    const keys = Object.keys(this.axiosClients);
+    let url;
+    for (const prefix of keys) {
+      const regRules = `^(${prefix})`;
+      const reg = new RegExp(regRules);
+      const res = reg.test(uri);
+      if (!res) continue;
+      const clientConfig = this.axiosClients[prefix];
+      const baseURL = clientConfig.baseURL;
+      // 去掉前缀
+      // url = uri.replace(reg, baseURL);
+      // 保留前缀(目前采用这一方式处理)
+      url = `${baseURL}${rb.originalUrl}`;
+      break;
+    }
+    if (!url) return;
+    const reqConfig: any = {
+      url,
+      method: rb.method,
+      headers: rb.header,
+    };
+    if (lowerCase(rb.method) === 'post') reqConfig.data = rb.body;
+    const res = await this.serviceAxios.request(reqConfig);
+    if (res.status !== 200) throw new Error('proxy service request error');
+    return res.data;
+  }
+
+  async getAxios(clientConfig: object): Promise<Axios.AxiosInstance> {
+    const rb: RequestBase = this.getRequstBase();
+    const axi = await this.sf.createInstance({
+      ...clientConfig,
+      header: get(rb, 'header'),
+    });
+    return axi;
+  }
+}

+ 20 - 0
test/controller/api.test.ts

@@ -0,0 +1,20 @@
+import { createApp, close, createHttpRequest } from '@midwayjs/mock';
+import { Framework } from '@midwayjs/koa';
+
+describe('test/controller/home.test.ts', () => {
+
+  it('should POST /api/get_user', async () => {
+    // create app
+    const app = await createApp<Framework>();
+
+    // make request
+    const result = await createHttpRequest(app).get('/api/get_user').query({ uid: 123 });
+
+    // use expect by jest
+    expect(result.status).toBe(200);
+    expect(result.body.message).toBe('OK');
+
+    // close app
+    await close(app);
+  });
+});

+ 21 - 0
test/controller/home.test.ts

@@ -0,0 +1,21 @@
+import { createApp, close, createHttpRequest } from '@midwayjs/mock';
+import { Framework } from '@midwayjs/koa';
+
+describe('test/controller/home.test.ts', () => {
+
+  it('should GET /', async () => {
+    // create app
+    const app = await createApp<Framework>();
+
+    // make request
+    const result = await createHttpRequest(app).get('/');
+
+    // use expect by jest
+    expect(result.status).toBe(200);
+    expect(result.text).toBe('Hello Midwayjs!');
+
+    // close app
+    await close(app);
+  });
+
+});

+ 28 - 0
tsconfig.json

@@ -0,0 +1,28 @@
+{
+  "compileOnSave": true,
+  "compilerOptions": {
+    "target": "es2018",
+    "module": "commonjs",
+    "moduleResolution": "node",
+    "experimentalDecorators": true,
+    "emitDecoratorMetadata": true,
+    "inlineSourceMap":true,
+    "noImplicitThis": true,
+    "noUnusedLocals": false,
+    "stripInternal": true,
+    "skipLibCheck": true,
+    "pretty": true,
+    "declaration": true,
+    "forceConsistentCasingInFileNames": true,
+    "typeRoots": [ "./typings", "./node_modules/@types"],
+    "outDir": "dist",
+    "rootDir": "src"
+  },
+  "exclude": [
+    "*.js",
+    "*.ts",
+    "dist",
+    "node_modules",
+    "test"
+  ]
+}