The last article in this series taught you how to write hello World and create students modules.

But that’s just a dry Get request; There is no Post request and no check for parameters; There is no use of logging.

This article continues to talk about, through the native ability of NestJs, to achieve Post requests, and do parameter checking, and finally use the native log module to achieve standardized log.

The full example can be found at Github.

Post request

As described in the previous article, the overall request will first go through the students.controller.ts -> and then to the students.service.ts.

Add Post method on students.service.ts

// students.service.ts
import { Controller, Get, Post } from '@nestjs/common';

// ...
@Controller('students')
export class StudentsController {
    constructor(private readonly studentsService: StudentsService) {}
  
    // @Get('who-are-you') ...

    @Post('who-are-you')
    whoAreYouPost() {
        return this.studentsService.ImStudent(); }}Copy the code

Use curl to access the address

/ / / / ✅ curl -x POST http://127.0.0.1:3000/students/who-are-you = > Im student %Copy the code

Post requests can be implemented quickly by replacing decorators.

Request parameters

Normal requests take parameters, but Get and Post take parameters slightly differently.

Let’s start with the Get request

Get request parameters

The parameters of a Get request are typically placed in the URL, where the @Query decorator comes in handy.

To transform the controller

// students.controller.ts
import { Controller, Get, Post, Query } from '@nestjs/common';
// ...
@Controller('students')
export class StudentsController {
    constructor(private readonly studentsService: StudentsService) {}
  
    @Get('who-are-you')
    whoAreYou(@Query('name') name: string) {
        return this.studentsService.ImStudent(name); }}Copy the code

To transform the service

// students.service.ts
import { Injectable } from '@nestjs/common';

@Injectable(a)export class StudentsService {
    ImStudent(name? :string) {
        return 'Im student '+ name; }}Copy the code

Access the URL through a browser

/ / ✅ http://localhost:3000/students/who-are-you? name=gdccwxx // => Im student gdccwxxCopy the code

So the Get request gets the name parameter

Post parameters

The Post parameter is a bit different, using the DTO transfer. Because the data transmitted over HTTP is a text type, you need to convert the text type to a variable that code can recognize.

The new students. The dtos. The ts

// src/students/dtos/students.dto.ts
export class StudentDto {
    name: string;
}
Copy the code

Edit students. Controller. Ts

// students.controller.ts
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
import { StudentDto } from './dtos/students.dto';
import { StudentsService } from './students.service';

@Controller('students')
export class StudentsController {
    constructor(private readonly studentsService: StudentsService) {}
  
    // @Get('who-are-you') ...

    @Post('who-are-you')
    whoAreYouPost(@Body() student: StudentDto) {
        return this.studentsService.ImStudent(student.name); }}Copy the code

Command line access

/ / ✅ curl -x POST - d "name = GDCCWXX" HTTP: / / http://127.0.0.1:3000/students/who-are-you / / = > Im student GDCCWXX %Copy the code

The parameters passed by the POST method are passed to the background by requesting the body. The data in the Body needs to be parsed through the @body decorator.

Parameter limitation and conversion

This section actually uses the concept of pipes, which we will implement with basic pipes, and more advanced uses will be found in Chapter 4

A Get request

ParseIntPipe is used for GET requests. A list of built-in pipes can be found here

The default url accessed by the browser is string, and the ParseIntPipe pipe converts string to number

This time we implement is by ID to find the name of the student.

Modify students. Service. Ts

// students.service.ts
import { Injectable } from '@nestjs/common';

@Injectable(a)export class StudentsService {
    // ImStudent...

    getStudentName(id: number) {
        const ID_NAME_MAP = {
            1: 'gdccwxx'};return ID_NAME_MAP[id] ?? 'not found'; }}Copy the code

Modify students. Controller. Ts

import { Body, Controller, Get, Post, Query, ParseIntPipe } from '@nestjs/common';
// ... 

@Controller('students')
export class StudentsController {
    constructor(private readonly studentsService: StudentsService) {}
  
    // @Get('who-are-you') ..

    // @Post('who-are-you') ...

    @Get('get-name-by-id')
    getNameById(@Query('id', ParseIntPipe) id: number) {
        return this.studentsService.getStudentName(id); }}Copy the code

Browsers use parameter access

/ / ❌ http://localhost:3000/students/get-name-by-id? id=gdccwxx // => { // statusCode: 400, // message: "Validation failed (numeric string is expected)", // error: "Bad Request" / /} / / ✅ http://localhost:3000/students/get-name-by-id? id=1 // => gdccwxxCopy the code

When an invalid request is used and cannot be converted, NestJs will report an error to handle the request, and the correct parameter will be converted to call the corresponding function. With a simple decorator reference, the NestJs framework can automatically check and convert parameters

A Post request

Post requests are slightly different and use a class-validator

Install the class – the validator

npm i --save class-validator class-transformer
Copy the code

Modify the main ts

// main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';


async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();
Copy the code

Modify student. Dto. Ts

import { IsNotEmpty, IsString } from 'class-validator';

export class StudentDto {
    @IsNotEmpty(a)@IsString(a)name: string;
}

Copy the code

Access from the command line

/ / / / ❌ curl -x POST http://127.0.0.1:3000/students/who-are-you = > {" statusCode ": 400, the" message ": [" name must be a The string ", "the name should not be empty", "error" : "Bad Request"} % / / ❌ curl -x POST at http://127.0.0.1:3000/students/who-are-you  -H 'Content-Type: application/json' -d '{"name": 1}' // => {"statusCode":400,"message":["name must be a string"],"error":"Bad Request"}% // ✅ curl -x POST http://127.0.0.1:3000/students/who-are-you - H 'the content-type: application/json - d' {" name ": "gdccwxx"}' // => Im student gdccwxx%Copy the code

At this point, the parameter verification part is also completed.

4. Custom decorators

In post requests where a large number of decorators are used, system decorators can be used for most scenarios, but there are specific needs where custom decorators are required.

An example is a scenario where each request is accompanied by the User field. GetUser is a very uncomfortable thing to do every time in the code, where custom decorators come in handy.

New SRC/common/decorators. Ts

// src/common/decorators.ts
import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const User = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) = > {
    const request = ctx.switchToHttp().getRequest(); // Get the request
    returnrequest.body.user; });Copy the code

Modify students. Controller. Ts

import { Body, Controller, Get, Post, Query, ParseIntPipe } from '@nestjs/common';
import { StudentsService } from './students.service';
import { User } from '.. /common/decorators';

@Controller('students')
export class StudentsController {
    constructor(private readonly studentsService: StudentsService) {}
    // @Get('who-are-you') ...
    // @Post('who-are-you') ...
    // @Get('get-name-by-id')...

    @Post('who-is-request')
    whoIsReq(@User() user: string) {
        returnuser; }}Copy the code

Command line access

/ / ✅ curl -x POST http://127.0.0.1:3000/students/who-is-request - H'Content-Type: application/json' -d '{"user": "gdccwxx"}'
// => gdccwxx% 
Copy the code

By customizing decorators and hanging them on functions, the code can elegantly retrieve excuses for who requested them.

Five, the log

Background interface requests are often accompanied by logs, which are crucial to background query. The NestJs framework also integrates logging, right out of the box.

There are three steps to using logs:

  • The main ts introducedLogger
  • The module introduces log components:private readonly logger = new Logger(StudentsService.name);
  • Introduce: this.logger.log(‘ student name is ${name} ‘) where you want to print;

Modify the main ts

// main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe, Logger } from '@nestjs/common';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: new Logger(),
  });
  // ...
}
// ...
Copy the code

Reference Logger build

import { Injectable, Logger } from '@nestjs/common';

@Injectable(a)export class StudentsService {
    private readonly logger = new Logger(StudentsService.name);

    ImStudent(name? :string) {
        this.logger.log(`student name is ${name}`);
        return 'Im student ' + name;
    }

    getStudentName(id: number) {
        this.logger.log(`get student id is ${id}`);
        const ID_NAME_MAP = {
            1: 'gdccwxx'};return ID_NAME_MAP[id] ?? 'not found'; }}Copy the code

Access interface, console output

The curl -x POST http://127.0.0.1:3000/students/who-are-you - H 'the content-type: application/json - d' {" name ":" GDCCWXX "} 'Copy the code

The full example can be found at Github.

So that’s the basic approach to handling requests, and the next article will show you how to connect to a database and use it

If you like the article, give it a thumbs up. You can find more exciting content on my personal blog