Detaillierte Erläuterung der Nest.js-Parametervalidierung und des benutzerdefinierten Rückgabedatenformats

Detaillierte Erläuterung der Nest.js-Parametervalidierung und des benutzerdefinierten Rückgabedatenformats

0x0 Parameterüberprüfung

Der Großteil der Parameterüberprüfung wird mithilfe der Pipeline-Methode in Nest.js implementiert. Weitere Einzelheiten finden Sie in der Dokumentation. Allerdings sind mir beim Schreiben einige Probleme begegnet, obwohl die Dokumentation eher undurchsichtig ist.

Erstellen Sie eine Abfrageschnittstelle, die einige Parameter enthält und diese in DTO-Strukturdaten umwandelt:

importiere { ApiProperty } von '@nestjs/swagger'

exportiere Klasse QueryUserDto {
 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Seitenzahl'
 })
 schreibgeschützte aktuelleSeite: Nummer

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Anzahl der Artikel'
 })
 schreibgeschützte Seitengröße: Zahl

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Benutzerkonto'
 })
 schreibgeschützter Benutzername?: Zeichenfolge

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Benutzerstatus'
 })
 schreibgeschützter ActiveStatus: Nummer

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Sortieren nach: ASC, DESC'
 })
 schreibgeschützte Reihenfolge: „DESC“ | „ASC“
}
 TYPOSKRIPT

Wenn die entsprechenden Parameter in der @Query-Anforderung übergeben werden, wird festgestellt, dass die erhaltenen Datentypen alle String sind. Nach Rücksprache mit den entsprechenden Dokumenten wird dann festgestellt, dass für die Konvertierung auch der Typ des Klassentransformators erforderlich ist:

importiere { ApiProperty } von '@nestjs/swagger'
importiere { Typ } von 'Klassentransformator'

exportiere Klasse QueryUserDto {
 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Seitenzahl'
 })
 @Typ(() => Zahl)
 schreibgeschützte aktuelleSeite: Nummer = 1

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Anzahl der Artikel'
 })
 @Typ(() => Zahl)
 schreibgeschützte Seitengröße: Zahl = 10

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Benutzerkonto'
 })
 schreibgeschützter Benutzername?: Zeichenfolge

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Benutzerstatus'
 })
 @Typ(() => Zahl)
 schreibgeschützter aktiverStatus: Nummer = 3

 @ApiProperty({
 erforderlich: false,
 Beschreibung: 'Sortieren nach: ASC, DESC'
 })
 schreibgeschützte Reihenfolge: 'DESC' | 'ASC' = 'DESC'
}

Aktivieren Sie dann die Transformationsoption in der Pipelinemethode ValidationPipe:

app.useGlobalPipes(
 neue ValidationPipe({
 transform: wahr
 })
)

Oder in app.modules.ts einfügen:

importiere { ValidationPipe } von '@nestjs/common'
importiere { APP_PIPE } von '@nestjs/core'

@Modul({
 Importe: [
 // ...
 ],
 Controller: [AppController],
 Anbieter:
 {
  angeben: APP_PIPE,
  useValue: neue ValidationPipe({
  transform: wahr
  })
 }
 ]
})

Der Unterschied zwischen den beiden Verwendungsmethoden besteht darin, ob es sich bei dem Programm um einen gemischten Anwendungstyp handelt.

Um Ärger zu vermeiden, schreibe ich es direkt in die globale Methode. Die vom Dienst schließlich erhaltenen Daten sind die vom Pipeline-Geschäft verarbeiteten Daten, und auf der Dienstebene müssen nicht viele Datentypbeurteilungen durchgeführt werden.

0x1 Passen Sie das Rückgabedatenformat an

Die vom Controller zurückgegebenen Daten stammen aus der Datenbanktabellenstruktur:

{
 "id": "d8d5a56c-ee9f-4e41-be48-5414a7a5712c",
 "Benutzername": "Akeem.Cremin",
 "Passwort": "$2b$10$kRcsmN6ewFC2GOs0TEg6TuvDbNzf1VGCbQf2fI1UeyPAiZCq9rMKm",
 "E-Mail": "[email protected]",
 "Spitzname": "Wallace Nicolas",
 "Rolle": "Benutzer",
 "isActive": wahr,
 "createdTime": "2021-03-24T15:24:26.806Z",
 "aktualisierteZeit": "2021-03-24T15:24:26.806Z"
}

Wenn Sie beispielsweise das Datenformat der endgültigen Rückgabeschnittstelle definieren müssen:

{
 "Statuscode": 200,
 "message": "Erfolgreich abgeschlossen",
 "Daten": {
  "id": "d8d5a56c-ee9f-4e41-be48-5414a7a5712c",
  "Benutzername": "Akeem.Cremin",
  "Passwort": "$2b$10$kRcsmN6ewFC2GOs0TEg6TuvDbNzf1VGCbQf2fI1UeyPAiZCq9rMKm",
  "E-Mail": "[email protected]",
  "Spitzname": "Wallace Nicolas",
  "Rolle": "Benutzer",
  "isActive": wahr,
  "createdTime": "2021-03-24T15:24:26.806Z",
  "aktualisierteZeit": "2021-03-24T15:24:26.806Z"
 }
}

Hier müssen Sie einen benutzerdefinierten Interceptor für Erfolgsanforderungen erstellen:

g in gemeinsam genutzt/Abfangjäger/Transformieren verschachteln
importiere { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } von '@nestjs/common'
importiere { Observable } von 'rxjs'
importiere { map } von 'rxjs/operators'
importiere { Request } von 'express'

Schnittstelle Antwort<T> {
 Daten: T
}

@Injizierbar()
exportiere Klasse TransformInterceptor<T> implementiert NestInterceptor<T, Response<T>> {
 intercept(Kontext: Ausführungskontext, nächster: CallHandler<T>): Observable<any> {
 const request = context.switchToHttp().getRequest<Anfrage>()
 Logger.log(request.url, „Normale Schnittstellenanforderung“)

 returniere nächsten.handle().pipe(
  Karte (Daten => {
  zurückkehren {
   Daten: Daten,
   Statuscode: 200,
   Meldung: „Anfrage erfolgreich“
  }
  })
 )
 }
}

Importieren Sie es dann in app.module.ts und verwenden Sie es:

importiere { ValidationPipe } von '@nestjs/common'
importiere { APP_INTERCEPTOR } von '@nestjs/core'

importiere { TransformInterceptor } von '@/shared/interceptor/transform.interceptor'

@Modul({
 Importe: [
 // ...
 ],
 Controller: [AppController],
 Anbieter:
 {
  bereitstellen: APP_INTERCEPTOR,
  verwenden Sie die Klasse: TransformInterceptor
 }
 ]
})

Beachten Sie jedoch die Reihenfolge von APP_INTERCEPTOR. Am besten setzen Sie TransformInterceptor an die erste Stelle, da es sonst fehlschlägt.

Fehlerfilter:

nest gf geteilt/Filter/httpException
importiere { ArgumentsHost, Catch, ExceptionFilter, HttpException, Logger } von '@nestjs/common'
importiere { Antwort, Anfrage } von 'express'

@Catch(HttpException)
Exportklasse HttpExceptionFilter implementiert ExceptionFilter {
 Fang(Ausnahme: HttpException, Host: ArgumentsHost) {
 const Kontext = host.switchToHttp()
 const Antwort = Kontext.getResponse<Antwort>()
 const request = context.getRequest<Anfrage>()
 const status = Ausnahme.getStatus()
 const message = Ausnahme.Nachricht

 Logger.log(`${request.url} - ${message}`, 'Abnormale Schnittstellenanforderung')

 Antwort.status(status).json({
  Statuscode: Status,
  Nachricht: Nachricht,
  Pfad: request.url,
  Zeitstempel: neues Date().toISOString()
 })
 }
}

Importieren Sie es dann in app.module.ts und verwenden Sie es:

importiere { ValidationPipe } von '@nestjs/common'
importiere { APP_FILTER } von '@nestjs/core'

importiere { HttpExceptionFilter } von '@/shared/filters/http-exception.filter'

@Modul({
 Importe: [
 // ...
 ],
 Controller: [AppController],
 Anbieter:
 {
  angeben: APP_FILTER,
  useClass: HttpExceptionFilter
 }
 ]
})

0x2 Ein Feld in der Entity-Klasse ausblenden

Ursprünglich wollte ich das Attribut @Exclude verwenden, um einige sensible Felder in der Datenbank auszublenden, stellte jedoch fest, dass es den speziellen Anforderungen nicht gerecht wurde. Wenn eine einzelne Instanz zurückgegeben wird, kann das Ausblenden erreicht werden, aber ich habe ein findAll, das nicht implementiert werden kann. Das Obige wird ausführlich im Dokument Serialization | NestJS - A progressive Node.js framework erläutert, aber hier gibt es eine andere Möglichkeit. Fügen Sie zunächst den stärkesensitiven Datenfeldern Attribute hinzu:

importiere { BaseEntity, Entity, Column, PrimaryGeneratedColumn } aus 'typeorm'

@Entity('Benutzer')
exportiere Klasse UserEntity erweitert BaseEntity {
 @PrimaryGeneratedColumn('uuid', {
  Kommentar: 'Benutzer-ID'
 })
 ID: Zeichenfolge

 @Spalte({
  Typ: "varchar",
  Länge: 50,
  einzigartig: wahr,
  Kommentar: „Angemeldeter Benutzer“
 })
 Benutzername: Zeichenfolge

 @Spalte({
  Typ: "varchar",
  Länge: 200,
  wählen Sie: false,
  Kommentar: 'Passwort'
 })
 Passwort: Zeichenfolge

select: false kann dieses Feld bei der Rückgabe von Abfrageergebnissen ausblenden, aber alle Abfragen, die dieses Feld betreffen, müssen dieses Feld hinzufügen, wie beispielsweise in meiner Anmeldeabfrage in user.service.ts:

const Benutzer = warte auf getRepository(UserEntity).
   .createQueryBuilder('Benutzer')
   .where('user.username = :Benutzername', { Benutzername })
   .addSelect('Benutzer.Passwort')
   .getOne()

.addSelect('user.password') Das Hinzufügen dieser Attributabfrage schließt das Kennwortfeld ein, andernfalls schließt die normale Abfragemethode dieses Feld nicht ein.

Zusammenfassen

Dies ist das Ende dieses Artikels über die Parametervalidierung von Nest.js und das benutzerdefinierte Rückgabedatenformat. Weitere Informationen zur Parametervalidierung und zum Datenformat von Nest.js finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

<<:  Beispielcode zum Konfigurieren von Nginx zur Unterstützung von https

>>:  Eine vollständige Anleitung zum Abfragen und Löschen doppelter Datensätze in MySQL

Artikel empfehlen

Grafisches Tutorial zur Installation und Konfiguration der MySQL-Version 8.0.24

Dieser Artikel zeichnet die Installations- und Ko...

Der Unterschied zwischen HTML Empty Link href="#" und href="javascript:void(0)"

# enthält eine Standortinformation. Der Standardan...

Vue-Beispielcode zur einfachen Implementierung von virtuellem Scrollen

Inhaltsverzeichnis Vorwort Rollprinzip erreichen ...

Implementierung der Docker-Bereitstellung des Nuxt.js-Projekts

Offizielle Docker-Dokumentation: https://docs.doc...

Lösung für „Keine Eingabedatei angegeben“ in nginx+php

Heute ist in meiner lokalen Entwicklungsumgebung ...

Entwicklungshandbuch für Chrome-Plugins (Erweiterungen) (vollständige Demo)

Inhaltsverzeichnis Vorne geschrieben Vorwort Was ...

Implementierung des Vue-Top-Tags-Browserverlaufs

Inhaltsverzeichnis Unsinn Implementierte Funktion...

JavaScript-Implementierung von Lupendetails

Inhaltsverzeichnis 1. Rendern 2. Umsetzungsprinzi...

Einführung in die Leistungsoptimierung von MySQL-Datenbanken

Inhaltsverzeichnis Warum optimieren? ? Wo soll ic...

So starten Sie Tomcat mit jsvc (als normaler Benutzer ausführen)

Einführung in jsvc In der Produktion sollte Tomca...

js, um einen einfachen Karusselleffekt zu erzielen

In diesem Artikel wird der spezifische Code von j...