nodejs企業級開発枠組みnet学習まとめ-5.NestJS入門は、monogoogle、multier、検証、キャッシュ、セキュリティなどを使用します.


モングース、マルチ、検証、キャッシュ、セキュリティなど
公式nestjs APIアドレス
1.netjsとmongoogleを結合する
1.1モングースの設置とnessの関連
cnpm i  @nestjs/mongoose mongoose --save
1.2接続データベースの設定
方式1、直接配置
// mongo.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
@Module({
	imports: [MongooseModule.forRoot('mongodb://localhost/demo', { useNewUrlParser: true })],
})
export class MongoModule { }
方式2,非同期配置
// mongo.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
@Module({
	imports: [
		MongooseModule.forRootAsync({
	        // 1.     ,  useFactory          
	        useFactory: () => ({
	            uri: 'mongodb://localhost/demo',
	            useNewUrlParser: true,
	        }),
	        // 2.  useClass  ,     ,  MongooseOptionsFactory  ,    
	        // useClass: MongooseConfigService,
	    }),
})
export class MongoModule { }
use Class:MongooseConfigServiceは、プロファイルを使用して配置されます.
// config.service.ts
import { Injectable } from '@nestjs/common';
import { MongooseOptionsFactory, MongooseModuleOptions } from '@nestjs/mongoose';

@Injectable()
export class MongooseConfigService implements MongooseOptionsFactory {
  createMongooseOptions(): MongooseModuleOptions {
    return {
      uri: 'mongodb://localhost/demo',
      useNewUrlParser: true,
    };
  }
}
次にimport { MongooseConfigService } from './config.service';を導入して使用する.
1.3配置schema
// user/user.schema.ts
import { Schema } from 'mongoose';
//         
export const UserSchema = new Schema({
    name: String,
    password: String,
    phone: String,
    email: String,
    times: Number,
});
1.4対応する文書セットを接続するモジュールを設定します.
// user/user.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { UserSchema } from './user.schema';
/**
 *   mongodb     ,  mongoose      
 */
@Module({
    imports: [MongooseModule.forFeature([{ name: 'users', schema: UserSchema }])],
})
export class UserModule { }
name:'users'は対応するmongodbのデータベース内のusersの集合であり、また forFeature , である.
1.5モングース検索データベースを配置するサービス
// user/user.service.ts
import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { User } from './user.interface';
import { CreateUserDto } from './create-user.dto';

@Injectable()
export class UserService {
  constructor(@InjectModel('users') private readonly userModel: Model<User>) {}

  async create(createUserDto: CreateUserDto): Promise<User> {
    const createdUser = new this.userModel(createUserDto); //       
    return await createdUser.save();
  }

  async findAll(): Promise<User[]> { //       
    return await this.userModel.find().exec();
  }
}
@InjectModel('users')の中のusersは対応するセットであり、対応するuserModelに注入し、その後、添削調査などを行うことができます.
import { User } from './user.interface';
import { CreateUserDto } from './create-user.dto';
//            dto
// user/user.interface.ts
export interface User {
    readonly name: string;
    readonly password: string;
    readonly phone: string;
    readonly email: string;
    readonly times: number;
}
// user/create-user.dto.ts
import { User } from './user.interface';

export class CreateUserDto implements User {
    public readonly name: string;
    public readonly phone: string;
    public readonly email: string;
    public readonly times: number;
    public readonly password: string;
}
1.6コントローラを開く
// user/user.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { User } from './user.interface';
import { UserService } from './user.service';
import { CreateUserDto } from './create-user.dto';

@Controller('/mongo')
export class UserController {
    public constructor(private readonly userService: UserService) { }
    @Get()
    public getUsers(): Promise<User[]> {
        return this.userService.findAll();
    }
    @Post()
    public createUser(@Body() createUserDto: CreateUserDto): Promise<CreateUserDto> {
        return this.userService.create(createUserDto);
    }
}

これで簡単なモンゴdb接続のデモが完成しました.
mogo.moduleモジュールをap.module.tsに配置して使用します.http://localhost:5000/mongoget要求を使用すると集合を取得でき、post要求は一つのデータを追加することができますが、対応するCreateUserDtoタイプのパラメータを伝達する必要があります.
2.ファイルをアップロードし、multierを使用する
2.1設置依存
cnpm i multer -S
2.2 upload.module.tsの配置
設定を同期
import { Module } from '@nestjs/common';
import { MulterModule } from '@nestjs/platform-express';
/**
 *        
 */
@Module({
    imports: [
     	MulterModule.register({
            dest: './uploadFile', //       ,       
            // preservePath: ,//     
            // fileFilter: , //      ,  ,            
            // storage: , //       ,         multer diskStorage    
            // limits: , //          
        }),
    ],
})
export class UploadModule { }
非同期設定
import { Module } from '@nestjs/common';
import { MulterModule } from '@nestjs/platform-express';
import { MulterConfigService } from './multerConfig.service';
/**
 *        
 */
@Module({
    imports: [
        //     
        MulterModule.registerAsync({
            // 1.   useFactory  
            // useFactory: () => ({
            //     dest: './uploadFile',
            // }),
            //     
            useClass: MulterConfigService,
        }),
    ],
})
export class UploadModule { }
multier Config.service.tsは、対応するファイルを配置しています.
import { Injectable } from '@nestjs/common';
import { MulterOptionsFactory, MulterModuleOptions } from '@nestjs/platform-express';
import { Request } from 'express';
import { diskStorage } from 'multer';
/**
 *          
 */
@Injectable()
export class MulterConfigService implements MulterOptionsFactory {
    createMulterOptions(): MulterModuleOptions {
        return {
            // dest: './uploadFile',
            fileFilter(req: Request, file: any, cb: (error: Error, acceptFile: boolean) => void): void {
                //          `cb`,
                //                ,           
                //        ,      `false`。 :
                // cb(null, false);
                //         ,    `true`。 :
                cb(null, true);
                //    ,               :
                // cb(new Error('I don\'t have a clue!'));
                // console.log(file.filename);
                // cb(null, false);
            },
            storage : diskStorage({
                destination: (req, file, cb) => {
                    cb(null, './uploadFile');
                },
                filename: (req, file, cb) => {
                    cb(null, file.originalname);
                },
            }),
        };
    }
}
fileFilter:フィルタを配置して、ファイルのアップロードを阻止できます.storge: dest , multer diskStorage,
destination:         
filename:                
2.3コントローラファイルを設定し、ファイルをアップロードする
単一ファイルアップロード
import { Controller, Post, UseInterceptors, UploadedFile, UploadedFiles } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
/**
 *      
 */
@Controller('/upload')
export class UploadController {
    /**         */
    @Post('/one')
    // FileInterceptor()      ,  fieldName(        HTML     )    options  。  MulterOptions      multer    
    @UseInterceptors(FileInterceptor('file', { // FileInterceptor       storage              
        // storage: diskStorage({
        //     // destination: (req, file, cb) => {
        //     //     cb(null, '/Users/liu/Desktop/test/');
        //     // },
        //     filename: (req, file, cb) => {
        //         cb(null, file.originalname);
        //     },
        // }),
    }))
    public uploadFile(@UploadedFile() file: any): any {
        console.log(file);
        return file;
        // return 'file             ';
    }
}
FileInterceptor: , , , , , upload.module.ts MulterModule.register UploadedFile , , multer , は、例えば、
{
    "fieldname": "file",
    "originalname": "a.jpg",
    "encoding": "7bit",
    "mimetype": "image/jpeg",
    "destination": "./uploadFile",
    "filename": "ajpg",
    "path": "uploadFile/a.jpg",
    "size": 11145
}
UploadedFiles@netjs/commonから導出する
ファイル配列をアップロードして、パラメータ名を共有します.
    @Post('/many')
    //         ,    FilesInterceptor()。          。fieldName(    ),maxCount             ,    MulterOptions  。
    @UseInterceptors(FilesInterceptor('files', 10))
    public uploadFileArray(@UploadedFiles() files: any): any {
        // console.log(files);
        return files;
    }
FilesInterceptorも同じく@netjs/plotform-expressから導出される.
複数のファイルをアップロードし、異なるパラメータ名
/**            */
    @Post('/manyFiles')
    @UseInterceptors(FileFieldsInterceptor([
        { name: 'avatar', maxCount: 3 },
        { name: 'background', maxCount: 1 },
    ]))
    public uploadFiles(@UploadedFiles() files: any): any {
        // console.log(files);
        // return 'files           ';
        return files;
    }
name ,maxCount UseInterceptorsも同じく@netjs/plotform-expressから導出される.
任意のファイルをアップロードし、パラメータ名を制限せず、name maxCountを設定する必要がありません.
    /**
     *     
     */
    @Post('/any')
    @UseInterceptors(AnyFilesInterceptor())
    public anyUploadFile(@UploadedFiles() files) {
        // console.log(files);
        // return 'files     ';
        return files;
    }
3.検証、class-validatorを使用する
インストール
cnpm i class-validator 
使用参考:class-validator(Gthubアドレス)
mail.tsにグローバル検証を設定するだけでいいです.
  app.useGlobalPipes(new ValidationPipe({
    disableErrorMessages: true, //                            。  ,        ,           。
    transform: true, //  ValidationPipe               DTO 。
  })); //     
あるいはmoduleの中のprovidersの中で直接配置します.
  {
      provide: APP_PIPE, // APP_PIPE   ,      
      useClass: ValidationPipe,
  },
, dto , , disableErrorMessages ture , 4.キャッシュcache-manager
キャッシュは非常に簡単な技術で、アプリケーションの性能を向上させるのに役立ちます.一時的なデータストアとして機能し、高性能データアクセスを提供する.
4.1取り付け
cnpm i --save cache-manager
4.2キャッシュ管理のモジュールを配置する
import { CacheModule, Module } from '@nestjs/common';
@Module({
  imports: [CacheModule.register()],
})
export class CacheConfigModule { }
4.3キャッシュを使用する必要があるところに、スクリーンショットを配置するか、または全体のmoduleを配置するか?
import { CacheInterceptor } from '@nestjs/common';
// @UseInterceptors(new CacheInterceptor(cacheManager,reflector)) //            ,    
//       
 {
      provide: APP_INTERCEPTOR,
      useClass: CacheInterceptor,
  },
5.プロローグserialization
5.1戻りたいデータの一部を除外するパラメータ
Exclude装飾器は、装飾された属性は除外されます.
import { Exclude } from 'class-transformer';

export class UserEntity {
  id: number;
  firstName: string;
  lastName: string;

  @Exclude()
  password: string;

  constructor(partial: Partial) {
    Object.assign(this, partial);
  }
}
5.2暴露属性@Expose()
Expose装飾器は、装飾後の対応するget方法がパラメータとして露出されます.
import { Expose } from 'class-transformer';
@Expose()
get fullName(): string {
  return `${this.firstName} ${this.lastName}`;
}
5.3 Transform露出の対象を選択する
@Transform()装飾器を使って他のデータ変換ができます.例えば、オブジェクト全体を返すのではなく、RoleEntityという名前を選択します.以下のように name age,
@Transform(role => ({name:role.name,age:role.age}))
role: RoleEntity;
Transformはいくつかの要因によって異なる場合があります.デフォルトの設定を上書きするには、@SerializOptions()装飾器を使ってください.
この@SerializOptions()デコレーションは輸入から@netjs/commonバッグです.
@SerializeOptions({
  // excludePrefixes: ['_'], //      _
})
@Get()
findOne(): UserEntity {
  return {};
}
6.ログログ
Nestはinternalのデフォルト実装を持っています.ロギングは実装中およびいくつかの異なる状況で使用されます.例えば発生した異常などです.しかし、ログレコードを完全に無効にしたり、カスタム実装を提供したり、メッセージを自分で処理したりすることを望む場合があります.
いくつかのタイプのログを有効にします.
const app = await NestFactory.create(ApplicationModule, {
  logger: ['error', 'warn'],
});
await app.listen(3000);
またはカスタムを使用して親のログを実現します.
import { LoggerService } from '@nestjs/common';

export class MyLogger implements LoggerService {
  log(message: string) {}
  error(message: string, trace: string) {}
  warn(message: string) {}
  debug(message: string) {}
  verbose(message: string) {}
}
カスタムログを使う
// logger:['error', 'warn']
logger:new MyLogger()
拡張ログ
//       Logger          ,   super          。
import { Logger } from '@nestjs/common';

export class MyLogger extends Logger {
  error(message: string, trace: string) {
    // add your tailored logic here
    super.error(message, trace);
  }
}
//   
// logger:new MyLogger()
または直接的なapp構成を使用します.
app.useLogger(app.get(MyLogger)); //                                  ,        。
7.安全
7.1対応するセキュリティ設定をインストールする
cnpm i helmet csurf express-rate-limit -S
helmet:は、よく知られているWeb・ホールの影響から、あなたのアプリケーションを保護する.一般に、Helmetは、セキュリティに関連したHTTPヘッダcsurf:を設定する12つのより小さな中間部品関数のセットにすぎず、局をまたいで偽造を要求する(CSRFまたはXSRFと呼ぶ).これは、許可されていない命令がWebアプリケーションから信頼されるユーザによって送信されるウェブサイトを悪用するものである.このような攻撃を緩和するには、csurfパッケージを使用することができます.express-rate-limit :は、過剰な要求を防止するためのライブラリであり、所定時間内の要求回数等を制限する.
7.2使用
import * as helmet from 'helmet';
import * as csurf from 'csurf';
import * as rateLimit from 'express-rate-limit';
	 //       
	 app.enableCors(); //   nest  
	//        HTTP  ,                     Web     。  ,Helmet  12            ,          HTTP (    )。
	 app.use(helmet());
	 //        (  CSRF XSRF)         ,          Web           。       ,     csurf   。
	 // app.use(csurf()); //        ,         ,    
	 //                 ,           。    ,NPM             。         。
	 app.use(
	   rateLimit({
	     windowMs: 15 * 60 * 1000, // 15 minutes
	     max: 100, // limit each IP to 100 requests per windowMs
	   }),
	 );
8.圧縮して、要求応答の体積を減らす
cnpm i --save compression
使用
import * as compression from 'compression';
// somewhere in your initialization file
app.use(compression());
9.Fastifyを使う
FastifyはNestのためにExpressに類似した方法で設計問題を解決するための良い代替フレームを提供する.しかし、fastifyはExpressよりずっと速くて、ほぼ二倍の基準テスト結果を実現しました.
9.1インストール
	cnpm i --save @nestjs/platform-fastify
9.2 fastifyを使用して配置する new FastifyAdapter(), FastifyAdapter
// src/main.ts
import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter({ logger: false, })
  );
  await app.listen(3000);
}
bootstrap();
9.3 Fastify処理リダイレクト応答の方式は、Expressとはやや異なる.

@Get()
index (@Res() res) {
  // send 302 redirect to /login
  res.status(302).redirect('/login');
}