diff --git a/README.md b/README.md index ca6d7fd..ad16aa7 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,17 @@ ## Description +```shell +npm i -g @nestjs/cli +``` + +```shell +npm run start:dev +``` + +http://127.0.0.1:3000/api/#/ + + + + + diff --git a/package-lock.json b/package-lock.json index 8710819..7814006 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,8 @@ "@nestjs/typeorm": "^8.0.3", "hbs": "^4.2.0", "mysql2": "^2.3.3", + "nestjs-rate-limiter": "^3.1.0", + "nestjs-real-ip": "^2.1.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", @@ -1718,6 +1720,11 @@ "resolved": "https://registry.npmmirror.com/@sqltools/formatter/-/formatter-1.2.3.tgz", "integrity": "sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg==" }, + "node_modules/@supercharge/request-ip": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@supercharge/request-ip/-/request-ip-1.2.0.tgz", + "integrity": "sha512-wlt6JW69MHqLY2M6Sm/jVyCojNRKq2CBvwH0Hbx24SFhDQQGkgEjeKxVutDxHSyrWixFaOSLXC27euzxijhyMQ==" + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz", @@ -5304,6 +5311,12 @@ "node": ">= 0.10" } }, + "node_modules/is_js": { + "version": "0.9.0", + "resolved": "https://registry.npmmirror.com/is_js/-/is_js-0.9.0.tgz", + "integrity": "sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==", + "peer": true + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -6927,6 +6940,26 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT" }, + "node_modules/nestjs-rate-limiter": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/nestjs-rate-limiter/-/nestjs-rate-limiter-3.1.0.tgz", + "integrity": "sha512-Qwr6daFvNppy038rs0iCQzX/uC3/czCC/2jATcETLIvyFmcBgySOMg7HGEquPKUZDX9lbc06Tn9L6U3QZS13HQ==", + "dependencies": { + "rate-limiter-flexible": "2.1.10" + } + }, + "node_modules/nestjs-real-ip": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/nestjs-real-ip/-/nestjs-real-ip-2.1.0.tgz", + "integrity": "sha512-nq3q1PtrvQ1UffDfE8AWUFTXm70wahTk+v708bdDJTSySi3YUTZ5T0wmFoDDOiiKSc5Phx8n8VW3EaFbtqRpIw==", + "dependencies": { + "@supercharge/request-ip": "^1.2.0" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0", + "request-ip": "^2.1.3" + } + }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmmirror.com/node-emoji/-/node-emoji-1.11.0.tgz", @@ -7572,6 +7605,11 @@ "node": ">= 0.6" } }, + "node_modules/rate-limiter-flexible": { + "version": "2.1.10", + "resolved": "https://registry.npmmirror.com/rate-limiter-flexible/-/rate-limiter-flexible-2.1.10.tgz", + "integrity": "sha512-Pa+8TPD4xYaiCUB5K4a/+j2FHDUe4HP1g49JmKEmkOkhqPaeVqxJsZuuVaza/svSCOT+V73vtsyBiSFK/e1yXw==" + }, "node_modules/raw-body": { "version": "2.5.1", "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.1.tgz", @@ -7684,6 +7722,15 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/request-ip": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/request-ip/-/request-ip-2.1.3.tgz", + "integrity": "sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ==", + "peer": true, + "dependencies": { + "is_js": "^0.9.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", @@ -10770,6 +10817,11 @@ "resolved": "https://registry.npmmirror.com/@sqltools/formatter/-/formatter-1.2.3.tgz", "integrity": "sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg==" }, + "@supercharge/request-ip": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@supercharge/request-ip/-/request-ip-1.2.0.tgz", + "integrity": "sha512-wlt6JW69MHqLY2M6Sm/jVyCojNRKq2CBvwH0Hbx24SFhDQQGkgEjeKxVutDxHSyrWixFaOSLXC27euzxijhyMQ==" + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz", @@ -13343,6 +13395,12 @@ "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is_js": { + "version": "0.9.0", + "resolved": "https://registry.npmmirror.com/is_js/-/is_js-0.9.0.tgz", + "integrity": "sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==", + "peer": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -14557,6 +14615,22 @@ "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "nestjs-rate-limiter": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/nestjs-rate-limiter/-/nestjs-rate-limiter-3.1.0.tgz", + "integrity": "sha512-Qwr6daFvNppy038rs0iCQzX/uC3/czCC/2jATcETLIvyFmcBgySOMg7HGEquPKUZDX9lbc06Tn9L6U3QZS13HQ==", + "requires": { + "rate-limiter-flexible": "2.1.10" + } + }, + "nestjs-real-ip": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/nestjs-real-ip/-/nestjs-real-ip-2.1.0.tgz", + "integrity": "sha512-nq3q1PtrvQ1UffDfE8AWUFTXm70wahTk+v708bdDJTSySi3YUTZ5T0wmFoDDOiiKSc5Phx8n8VW3EaFbtqRpIw==", + "requires": { + "@supercharge/request-ip": "^1.2.0" + } + }, "node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmmirror.com/node-emoji/-/node-emoji-1.11.0.tgz", @@ -14987,6 +15061,11 @@ "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, + "rate-limiter-flexible": { + "version": "2.1.10", + "resolved": "https://registry.npmmirror.com/rate-limiter-flexible/-/rate-limiter-flexible-2.1.10.tgz", + "integrity": "sha512-Pa+8TPD4xYaiCUB5K4a/+j2FHDUe4HP1g49JmKEmkOkhqPaeVqxJsZuuVaza/svSCOT+V73vtsyBiSFK/e1yXw==" + }, "raw-body": { "version": "2.5.1", "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.1.tgz", @@ -15068,6 +15147,15 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, + "request-ip": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/request-ip/-/request-ip-2.1.3.tgz", + "integrity": "sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ==", + "peer": true, + "requires": { + "is_js": "^0.9.0" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", diff --git a/package.json b/package.json index e3fd892..e429f39 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "@nestjs/typeorm": "^8.0.3", "hbs": "^4.2.0", "mysql2": "^2.3.3", + "nestjs-rate-limiter": "^3.1.0", + "nestjs-real-ip": "^2.1.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", diff --git a/src/aaa/aaa.controller.spec.ts b/src/aaa/aaa.controller.spec.ts new file mode 100644 index 0000000..a911dc3 --- /dev/null +++ b/src/aaa/aaa.controller.spec.ts @@ -0,0 +1,17 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +describe('AaaController', () => { + let controller: AaaController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [AaaController], + }).compile(); + + controller = module.get(AaaController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/app.controller.ts b/src/app.controller.ts index 4dd44d9..7519eff 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -14,8 +14,10 @@ import { import { AppService } from './app.service'; import { Request } from 'express'; import { ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { RealIP } from 'nestjs-real-ip'; @Controller() +@ApiTags('基本使用') export class AppController { // constructor(private readonly appService: AppService) {} @@ -24,6 +26,20 @@ export class AppController { // return this.appService.getHello(); // } // 基础路由 + + @Get('/getip') + @ApiTags('获取访问者IP') + getIP(@RealIP() ip: string): string { + // npm i nestjs-real-ip + return ip; + } + + @Get() + @Redirect('/api', 302) + hello() { + return ''; + } + @Get('/r1') @HttpCode(200) getR1(): string { diff --git a/src/app.module.ts b/src/app.module.ts index 9631ab9..c68d60d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -3,11 +3,17 @@ import { AppController } from './app.controller'; import { AppService } from './app.service'; import { ScheduleModule } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { RateLimiterModule } from 'nestjs-rate-limiter'; + import User from './entity/user'; import { TechModule } from './apps/tech'; +import { CatsModule } from './apps/tech/cats/cats.module'; +import { RateModule } from './apps/rate'; @Module({ imports: [ TechModule, + RateModule, + RateLimiterModule, ScheduleModule.forRoot(), TypeOrmModule.forRoot({ type: 'mysql', @@ -21,6 +27,7 @@ import { TechModule } from './apps/tech'; autoLoadEntities: true, // 是否自动导入 logging: true, // 打印日志 }), + CatsModule, ], controllers: [AppController], providers: [AppService], diff --git a/src/apps/rate/controller.ts b/src/apps/rate/controller.ts new file mode 100644 index 0000000..37470ce --- /dev/null +++ b/src/apps/rate/controller.ts @@ -0,0 +1,18 @@ +import { Controller, Get } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { RateLimit } from 'nestjs-rate-limiter'; + +@Controller('rate') +@ApiTags('Rate频率限制') +export default class RateController { + @Get('/t1') + @RateLimit({ + keyPrefix: 'sign-up', + points: 1, + duration: 1, + errorMessage: '系统忙', + }) + T1() { + return '频率限制T1'; + } +} diff --git a/src/apps/rate/index.ts b/src/apps/rate/index.ts new file mode 100644 index 0000000..456ace5 --- /dev/null +++ b/src/apps/rate/index.ts @@ -0,0 +1,8 @@ +// npm i nestjs-rate-limiter +import { Module } from '@nestjs/common'; +import RateController from './controller'; +@Module({ + controllers: [RateController], + providers: [], +}) +export class RateModule {} diff --git a/src/apps/tech/cats/cats.module.ts b/src/apps/tech/cats/cats.module.ts new file mode 100644 index 0000000..4e75557 --- /dev/null +++ b/src/apps/tech/cats/cats.module.ts @@ -0,0 +1,4 @@ +import { Module } from '@nestjs/common'; + +@Module({}) +export class CatsModule {} diff --git a/src/apps/tech/controller/tech.ts b/src/apps/tech/controller/tech.ts index 68175c5..2ce9f8c 100644 --- a/src/apps/tech/controller/tech.ts +++ b/src/apps/tech/controller/tech.ts @@ -1,8 +1,10 @@ import { Controller, Get } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import TechEntity from '../entity/tech'; @Controller('/tech') +@ApiTags('ORM使用') export default class TechController { @InjectRepository(TechEntity) private tech: Repository; diff --git a/yarn.lock b/yarn.lock index 87cfb09..5de746a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -723,6 +723,11 @@ "resolved" "https://registry.npmmirror.com/@sqltools/formatter/-/formatter-1.2.3.tgz" "version" "1.2.3" +"@supercharge/request-ip@^1.2.0": + "integrity" "sha512-wlt6JW69MHqLY2M6Sm/jVyCojNRKq2CBvwH0Hbx24SFhDQQGkgEjeKxVutDxHSyrWixFaOSLXC27euzxijhyMQ==" + "resolved" "https://registry.npmmirror.com/@supercharge/request-ip/-/request-ip-1.2.0.tgz" + "version" "1.2.0" + "@tootallnate/once@1": "integrity" "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" "resolved" "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz" @@ -2879,6 +2884,11 @@ "resolved" "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz" "version" "1.9.1" +"is_js@^0.9.0": + "integrity" "sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==" + "resolved" "https://registry.npmmirror.com/is_js/-/is_js-0.9.0.tgz" + "version" "0.9.0" + "is-arrayish@^0.2.1": "integrity" "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" "resolved" "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz" @@ -3835,6 +3845,20 @@ "resolved" "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz" "version" "2.6.2" +"nestjs-rate-limiter@^3.1.0": + "integrity" "sha512-Qwr6daFvNppy038rs0iCQzX/uC3/czCC/2jATcETLIvyFmcBgySOMg7HGEquPKUZDX9lbc06Tn9L6U3QZS13HQ==" + "resolved" "https://registry.npmmirror.com/nestjs-rate-limiter/-/nestjs-rate-limiter-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "rate-limiter-flexible" "2.1.10" + +"nestjs-real-ip@^2.1.0": + "integrity" "sha512-nq3q1PtrvQ1UffDfE8AWUFTXm70wahTk+v708bdDJTSySi3YUTZ5T0wmFoDDOiiKSc5Phx8n8VW3EaFbtqRpIw==" + "resolved" "https://registry.npmmirror.com/nestjs-real-ip/-/nestjs-real-ip-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "@supercharge/request-ip" "^1.2.0" + "node-emoji@1.11.0": "integrity" "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==" "resolved" "https://registry.npmmirror.com/node-emoji/-/node-emoji-1.11.0.tgz" @@ -4212,6 +4236,11 @@ "resolved" "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz" "version" "1.2.1" +"rate-limiter-flexible@2.1.10": + "integrity" "sha512-Pa+8TPD4xYaiCUB5K4a/+j2FHDUe4HP1g49JmKEmkOkhqPaeVqxJsZuuVaza/svSCOT+V73vtsyBiSFK/e1yXw==" + "resolved" "https://registry.npmmirror.com/rate-limiter-flexible/-/rate-limiter-flexible-2.1.10.tgz" + "version" "2.1.10" + "raw-body@2.4.3": "integrity" "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==" "resolved" "https://registry.npmmirror.com/raw-body/-/raw-body-2.4.3.tgz" @@ -4302,6 +4331,13 @@ "resolved" "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz" "version" "3.2.0" +"request-ip@^2.1.3": + "integrity" "sha512-J3qdE/IhVM3BXkwMIVO4yFrvhJlU3H7JH16+6yHucadT4fePnR8dyh+vEs6FIx0S2x5TCt2ptiPfHcn0sqhbYQ==" + "resolved" "https://registry.npmmirror.com/request-ip/-/request-ip-2.1.3.tgz" + "version" "2.1.3" + dependencies: + "is_js" "^0.9.0" + "require-directory@^2.1.1": "integrity" "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" "resolved" "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz"