Verständnis von URLs und Implementierung eines URL-Shorteners mit NestJS
URL, eine Abkürzung für Uniform Resource Locator, ist eine Adresse, die einer einzigartigen Ressource im Web zugewiesen wird. Da eine URL einzigartig ist, können keine zwei Ressourcen dieselbe URL haben.
Die Länge und Komplexität von URLs variiert. Eine URL kann so kurz wie example.com oder so lang wie http://llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch.co.uk sein. Komplexe URLs können unschön sein, Probleme bei der Suchmaschinenoptimierung (SEO) verursachen und sich negativ auf Marketingpläne auswirken. URL-Shortener ordnen einer langen URL eine kürzere URL zu und leiten den Benutzer zur ursprünglichen URL weiter, wenn die kurze URL verwendet wird.
Einleitung
In diesem Tutorial erstellen Sie einen URL-Shortener mit NestJS. Zuerst implementieren Sie die Logik zur Verkürzung und Weiterleitung von URLs in einem Service. Anschließend erstellen Sie Routen-Handler, um die Verkürzungs- und Weiterleitungsanfragen zu ermöglichen.
Voraussetzungen
Um diesem Tutorial zu folgen, benötigen Sie:
- Eine lokale Entwicklungsumgebung für Node.js Version 16 oder höher. Folgen Sie dem Tutorial „How To Install Node.js and Create a Local Development Environment“, das zu Ihrem System passt.
- Die auf Ihrem System installierte NestJS CLI, die Sie in Schritt 1 einrichten, sowie Grundkenntnisse in NestJS. Sehen Sie sich „Getting Started with NestJS“ an.
- Grundkenntnisse in TypeScript. Sie können die Serie „How To Code in TypeScript“ durchsehen, um mehr zu erfahren.
Schritt 1 — Vorbereitung Ihrer Entwicklungsumgebung
In diesem Schritt richten Sie alles ein, was Sie benötigen, um die Logik zur URL-Verkürzung zu implementieren. Sie installieren NestJS global, generieren ein neues NestJS-Anwendungsgrundgerüst, installieren Abhängigkeiten und erstellen das Modul, den Service und den Controller Ihres Projekts.
Zuerst installieren Sie die Nest CLI global, falls Sie sie nicht bereits installiert haben. Sie verwenden diese CLI, um das Projektverzeichnis und die erforderlichen Dateien zu generieren. Führen Sie den folgenden Befehl aus, um die Nest CLI zu installieren:
npm install -g @nestjs/cli
Das `-g`-Flag installiert die Nest CLI global auf Ihrem System.
Sie sehen die folgende Ausgabe:
...
added 249 packages, and audited 250 packages in 3m
39 packages are looking for funding
run npm fund for details
found 0 vulnerabilities
Dann verwenden Sie den Befehl `new`, um das Projekt zu erstellen und die erforderlichen Grunddateien zu generieren:
nest new URL-shortener
Sie sehen die folgende Ausgabe:
...
⚡ We will scaffold your app in a few seconds..
CREATE url-shortener/.eslintrc.js (631 bytes)
CREATE url-shortener/.prettierrc (51 bytes)
CREATE url-shortener/nest-cli.json (118 bytes)
CREATE url-shortener/package.json (2002 bytes)
CREATE url-shortener/README.md (3339 bytes)
CREATE url-shortener/tsconfig.build.json (97 bytes)
CREATE url-shortener/tsconfig.json (546 bytes)
CREATE url-shortener/src/app.controller.spec.ts (617 bytes)
CREATE url-shortener/src/app.controller.ts (274 bytes)
CREATE url-shortener/src/app.module.ts (249 bytes)
CREATE url-shortener/src/app.service.ts (142 bytes)
CREATE url-shortener/src/main.ts (208 bytes)
CREATE url-shortener/test/app.e2e-spec.ts (630 bytes)
CREATE url-shortener/test/jest-e2e.json (183 bytes)
Wechseln Sie in Ihr erstelltes Projektverzeichnis:
cd url-shortener
Alle weiteren Befehle werden in diesem Verzeichnis ausgeführt.
Hinweis: Die NestJS CLI erstellt die Dateien `app.controller.ts`, `app.controller.spec.ts` und `app.service.ts`, wenn Sie ein neues Projekt generieren. Da Sie diese in diesem Tutorial nicht benötigen, können Sie sie entweder löschen oder ignorieren.
Installation der erforderlichen Abhängigkeiten für Ihren URL-Shortener
Als Nächstes installieren Sie die erforderlichen Abhängigkeiten. Dieses Tutorial erfordert einige Abhängigkeiten, die Sie mit dem Standard-Paketmanager von NodeJS `npm` installieren. Die erforderlichen Abhängigkeiten umfassen TypeORM, SQLite, Class-validator, Class-transformer und Nano-ID.
Führen Sie den Befehl aus, um TypeORM und sein dediziertes NestJS-Paket zu installieren:
npm install @nestjs/typeorm typeorm
Der folgende Befehl installiert SQLite:
npm install sqlite3
Führen Sie den folgenden Befehl aus, um class-validator
zu installieren:
npm install class-validator
Führen Sie den folgenden Befehl aus, um class-transformer
zu installieren:
npm install class-transformer
Der folgende Befehl installiert Nano-ID:
npm install nanoid@^3.0.0
Nachdem Sie die erforderlichen Abhängigkeiten installiert haben, generieren Sie das Modul, den Service und den Controller des Projekts mithilfe der Nest CLI. Das Modul organisiert Ihr Projekt, der Service übernimmt die gesamte Logik des URL-Shorteners, und der Controller kümmert sich um die Routen.
Führen Sie den folgenden Befehl aus, um Ihr Modul zu generieren:
nest generate module url
Sie sehen die folgende Ausgabe:
CREATE src/url/url.module.ts (80 bytes)
UPDATE src/app.module.ts (304 bytes)
Als Nächstes führen Sie den folgenden Befehl aus, um Ihren Service zu generieren:
nest generate service url --no-spec
Das Flag --no-spec
sorgt dafür, dass die Nest CLI die Dateien ohne zugehörige Testdateien generiert. Diese Testdateien werden in diesem Tutorial nicht benötigt.
Sie sehen die folgende Ausgabe:
CREATE src/url/url.service.ts (87 bytes)
UPDATE src/url/url.module.ts (151 bytes)
Führen Sie abschließend den folgenden Befehl aus, um Ihren Controller zu generieren:
nest generate controller url --no-spec
Sie sehen die folgende Ausgabe:
CREATE src/url/url.controller.ts (95 bytes)
UPDATE src/url/url.module.ts (233 bytes)
In diesem Schritt haben Sie Ihre Anwendung und die meisten Dateien erstellt, die für die Entwicklung benötigt werden. Im nächsten Schritt verbinden Sie Ihre Anwendung mit einer Datenbank.
Schritt 2 — Verbindung Ihrer Anwendung mit einer Datenbank
In diesem Schritt erstellen Sie eine Entität, um die URL-Ressource in Ihrer Datenbank zu modellieren. Eine Entität ist eine Datei, die die notwendigen Eigenschaften der gespeicherten Daten enthält. Außerdem erstellen Sie ein Repository als Zugriffsebene zwischen Ihrer Anwendung und der Datenbank.
Erstellen und öffnen Sie mit Nano oder Ihrem bevorzugten Texteditor eine Datei im Ordner src/url
mit dem Namen url.entity.ts
:
nano src/url/url.entity.ts
Diese Datei wird die Entität zur Modellierung Ihrer Daten enthalten.
Fügen Sie in Ihre Datei src/url/url.entity.ts
den folgenden TypeScript-Code ein:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Url {
@PrimaryGeneratedColumn()
id: number;
@Column()
urlCode: string;
@Column()
longUrl: string;
@Column()
shortUrl: string;
}
Importieren Sie zunächst die Dekoratoren Entity
, Column
und PrimaryGeneratedColumn
aus 'typeorm'
.
Der Code erstellt und exportiert eine Klasse Url
, die mit dem Dekorator Entity
annotiert ist, der eine Klasse als Entität markiert.
Speichern und schließen Sie die Datei.
Schritt 3 — Implementierung der Servicelogik
In diesem Schritt implementieren Sie die Logik Ihres Services mit zwei Methoden. Die erste Methode, shortenUrl
, enthält die gesamte Logik zur Verkürzung von URLs. Die zweite Methode, redirect
, enthält die gesamte Logik, um Benutzer zur ursprünglichen URL weiterzuleiten.
Servicezugriff auf das Repository bereitstellen
Bevor Sie diese Methoden implementieren, geben Sie Ihrem Service Zugriff auf Ihr Repository, damit Ihre Anwendung Daten in der Datenbank lesen und schreiben kann.
Öffnen Sie zuerst die Datei src/url/url.service.ts
:
nano src/url/url.service.ts
Fügen Sie die folgenden hervorgehobenen Zeilen in die bestehende Datei ein:
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { Url } from './url.entity';
@Injectable()
export class UrlService {
constructor(
@InjectRepository(Url)
private repo: Repository,
) {}
}
Sie importieren Repository
aus typeorm
, InjectRepository
aus @nestjs/typeorm
und Url
aus ./url.entity
.
In Ihrer UrlService
-Klasse erstellen Sie einen Konstruktor. Innerhalb des Konstruktors deklarieren Sie eine private Variable repo
als Parameter. Anschließend weisen Sie repo
einen Typ von Repository
mit einem generischen Typ von Url
zu. Sie annotieren die Variable repo
mit dem Dekorator @InjectRepository
und übergeben Url
als Argument.
Speichern und schließen Sie die Datei.
Erstellen der Methode shortenUrl
Die Methode shortenUrl
übernimmt den Großteil der Logik zur URL-Verkürzung. Sie nimmt einen Parameter url
vom Typ ShortenURLDto
.
Öffnen Sie die Datei src/url/url.service.ts
erneut:
nano src/url/url.service.ts
Fügen Sie die folgenden hervorgehobenen Zeilen hinzu:
import {
BadRequestException,
Injectable,
NotFoundException,
UnprocessableEntityException
} from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { Url } from './url.entity';
import { ShortenURLDto } from './dtos/url.dto';
import { nanoid } from 'nanoid';
import { isURL } from 'class-validator';
@Injectable()
export class UrlService {
constructor(
@InjectRepository(Url)
private repo: Repository,
) {}
async shortenUrl(url: ShortenURLDto) {
const { longUrl } = url;
// Überprüfen, ob die URL gültig ist
if (!isURL(longUrl)) {
throw new BadRequestException('String must be a valid URL');
}
const urlCode = nanoid(10);
const baseURL = 'http://localhost:3000';
try {
// Überprüfen, ob die URL bereits verkürzt wurde
let url = await this.repo.findOneBy({ longUrl });
if (url) return url.shortUrl;
// Wenn sie nicht existiert, verkürzen Sie sie
const shortUrl = `${baseURL}/${urlCode}`;
// Neue Datenbankeintrag erstellen
url = this.repo.create({
urlCode,
longUrl,
shortUrl,
});
this.repo.save(url);
return url.shortUrl;
} catch (error) {
console.log(error);
throw new UnprocessableEntityException('Server Error');
}
}
}
Speichern und schließen Sie die Datei.
Erstellen der Methode redirect
Die Methode redirect
enthält die Logik, die Benutzer zur ursprünglichen URL weiterleitet.
Fügen Sie die folgende Logik am Ende Ihrer UrlService
-Klasse hinzu:
async redirect(urlCode: string) {
try {
const url = await this.repo.findOneBy({ urlCode });
if (url) return url;
} catch (error) {
console.log(error);
throw new NotFoundException('Resource Not Found');
}
}
Die Methode redirect
nimmt urlCode
als Argument und versucht, eine Ressource in der Datenbank zu finden, die mit dem urlCode
übereinstimmt. Wenn die Ressource existiert, wird sie zurückgegeben. Andernfalls wird ein NotFoundException
-Fehler ausgelöst.
Speichern und schließen Sie die Datei.
Schritt 4 — Implementierung der Controller-Logik
In diesem Schritt erstellen Sie zwei Routen-Handler: einen POST
-Handler zur Verarbeitung von Verkürzungsanfragen und einen GET
-Handler zur Verarbeitung von Weiterleitungsanfragen.
Vorbereiten des Controllers
Zuerst öffnen Sie die Datei src/url/url.controller.ts
:
nano src/url/url.controller.ts
Fügen Sie die hervorgehobenen Zeilen hinzu:
import { Body, Controller, Get, Param, Post, Res } from '@nestjs/common';
import { UrlService } from './url.service';
import { ShortenURLDto } from './dtos/url.dto';
@Controller()
export class UrlController {
constructor(private service: UrlService) {}
@Post('shorten')
shortenUrl(
@Body()
url: ShortenURLDto,
) {
return this.service.shortenUrl(url);
}
@Get(':code')
async redirect(
@Res() res,
@Param('code')
code: string,
) {
const url = await this.service.redirect(code);
return res.redirect(url.longUrl);
}
}
In dieser Datei:
- Importieren Sie
Body
,Controller
,Get
,Param
,Post
undRes
aus@nestjs/common
. - Importieren Sie
UrlService
aus./url.service
undShortenURLDto
aus./dtos/url.dto
. - Erstellen Sie den Konstruktor, der
UrlService
initialisiert. - Fügen Sie die Methode
shortenUrl
hinzu, die auf Anfragen mit der Route/shorten
reagiert und die MethodeshortenUrl
im Service aufruft. - Fügen Sie die Methode
redirect
hinzu, die auf Anfragen mit einem URL-Code in der Route reagiert und die Methoderedirect
im Service aufruft.
Speichern und schließen Sie die Datei.
Schritt 5 — Testen des URL-Shorteners
In diesem Schritt testen Sie den URL-Shortener, den Sie in den vorherigen Schritten erstellt haben.
Anwendung starten
Starten Sie Ihre Anwendung mit dem folgenden Befehl:
npm run start
Sie sehen die folgende Ausgabe:
[Nest] 12640 - 06/08/2022, 16:20:04 LOG [NestFactory] Starting Nest application...
[Nest] 12640 - 06/08/2022, 16:20:07 LOG [InstanceLoader] AppModule dependencies initialized +2942ms
[Nest] 12640 - 06/08/2022, 16:20:07 LOG [InstanceLoader] TypeOrmModule dependencies initialized +1ms
[Nest] 12640 - 06/08/2022, 16:20:08 LOG [InstanceLoader] TypeOrmCoreModule dependencies initialized +257ms
[Nest] 12640 - 06/08/2022, 16:20:08 LOG [InstanceLoader] UrlModule dependencies initialized +4ms
[Nest] 12640 - 06/08/2022, 16:20:08 LOG [RouterExplorer] Mapped {/shorten, POST} route +7ms
[Nest] 12640 - 06/08/2022, 16:20:08 LOG [RouterExplorer] Mapped {/:code, GET} route +2ms
[Nest] 12640 - 06/08/2022, 16:20:08 LOG [NestApplication] Nest application successfully started +7ms
API testen
Öffnen Sie ein neues Terminal und verwenden Sie curl
oder ein bevorzugtes API-Testwerkzeug, um eine POST
-Anfrage an http://localhost:3000/shorten
zu senden:
curl -d "{\"longUrl\":\"http://llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch.co.uk\"}" -H "Content-Type: application/json" http://localhost:3000/shorten
Sie erhalten als Antwort eine kurze URL, z. B.:
http://localhost:3000/MWBNHDiloW
Kopieren Sie die kurze URL, fügen Sie sie in Ihren Browser ein und drücken Sie ENTER. Sie werden zur ursprünglichen Ressource weitergeleitet.
Fazit
In diesem Tutorial haben Sie einen URL-Shortener mit NestJS erstellt. NestJS bietet Typsicherheit und eine Architektur, die Ihre Anwendung sicherer, wartungsfreundlicher und skalierbarer macht. Weitere Informationen finden Sie in der offiziellen Dokumentation von NestJS.