In diesem Beitrag zeigen wir Ihnen, wie Sie einen URL-Kürzungsdienst wie bit.ly oder goo.gl mit Express.js (Node.js) und MongoDB erstellen. Hier ist eine Demo des Endprodukts, das wir über unsere MongoDB-Hosting-Plattform erstellen werden.
Wie funktioniert ein URL-Shortener?
Auf einer sehr hohen Ebene funktioniert der URL-Kürzer, indem er eine eingegebene URL nimmt und eine relativ verkürzte Version erstellt, die in ein einfach zu teilendes Format vereinfacht wird. Der verkürzte Hash wird durch Basiscodierung eines automatisch inkrementierten Zählers generiert und erzeugt einen mindestens drei Zeichen langen Hash, der sich erhöht, wenn die Anzahl gespeicherter URLs zunimmt.
Wenn die verkürzte Version der URL besucht wird, entschlüsselt der Dienst den Hash, um die in MongoDB gespeicherte Original-URL abzurufen und Ihren Benutzer dann dorthin weiterzuleiten.
Erste Schritte
Hier ist eine Liste der Technologien, die wir verwenden, um den URL-Shortener in diesem Tutorial zu erstellen:
-
Express.js (Node.js-Back-End)
Ein Webanwendungs-Framework für Node.js. Wir werden es verwenden, um eine API zum Kürzen von URLs zu erstellen und Benutzer auf die ursprüngliche URL umzuleiten.
-
MongoDB (URLs speichern)
Eine NoSQL-Datenbank, perfekt für diese Anwendung. Es bietet ein flexibles Schemadesign und ist einfach zu starten. In diesem Tutorial verwenden wir einen freigegebenen MongoDB-Cluster auf ScaleGrid. Die Einrichtung dauert weniger als 5 Minuten und Sie können hier eine kostenlose 30-Tage-Testversion erstellen, um loszulegen.
-
HTML, CSS, JavaScript (Frontend)
HTML, CSS und JavaScript werden verwendet, um das Front-End der Anwendung zu erstellen, die Ihre Nutzer zum Kürzen von URLs verwenden werden.
URL-Shortener-Tutorial
-
Richten Sie die MongoDB-Datenbankstruktur ein
Beginnen wir mit der Erstellung eines freigegebenen MongoDB-Clusters auf ScaleGrid. Dies ist der einfachste Weg, um schnell einen Cluster zu erstellen, aber Sie können MongoDB auch auf Ihrem Computer installieren und dort loslegen.
Sobald der Cluster erstellt ist, erhalten Sie eine Verbindungszeichenfolge, die Sie mit einem einzigen Klick von Ihrer Cluster-Detailseite kopieren können. Wir benötigen diese Zeichenfolge, um von unserer Anwendung aus eine Verbindung zum Cluster herzustellen. Denken Sie daran, niemals Ihre Verbindungszeichenfolge mit anderen zu teilen.
Wir benötigen zwei Sammlungen für den URL-Shortener:
-
Sammlung 1
Eine Sammlung zum Speichern der URL und der dynamisch generierten ID:
-
Sammlung 2
Eine Sammlung zur Verwaltung des Zählers, der automatisch erhöht wird, wenn eine neue URL in der vorherigen Sammlung gespeichert wird. Ein neues Dokument wird in der vorherigen Sammlung mit diesem neu inkrementierten Zähler erstellt:
Es ist wichtig zu beachten, dass wir die Hashes nirgendwo in der Datenbank speichern. Der Hash wird mit dem allgemeinen Algorithmus basencodiert und dynamisch decodiert, was zu der eindeutigen ID führt, die in der ersten Sammlung gespeichert wird. Diese ID holt uns dann die Original-URL, zu der der Benutzer umgeleitet wird.
Für dieses Tutorial verwenden wir den gemeinsamen base64-Kodierungs- und Dekodierungsmechanismus, um unseren einzigartigen verkürzten Hash zu generieren. Weitere Informationen zum Codieren/Decodieren von Zeichenfolgen mit base64 finden Sie in unserem folgenden MDN-Webdokument.
-
-
Richten Sie das Express.js-Backend ein
Hier ist eine Liste der Abhängigkeiten, die zum Einrichten unseres Node.js-Backends erforderlich sind:
- Express (Basis-App)
- body-parser (Add-on zum Parsen von Daten, die über HTTP-Anfragen gesendet werden)
- btoa (Base64-Kodierung)
- atob (Base64-Decodierung)
- dotenv (Speichern der Verbindungszeichenfolge in einer .env-Datei für Entwicklungszwecke)
- mongoose (Adapter für MongoDB auf Node.js)
Hier ist eine Beispielversion von package.json, die Sie zum Einrichten der App verwenden können:
{ "name":"sg-url-shortener", "version":"1.0.0", "description":"Ein einfacher URL-Shortener, der mit Node.js und MongoDB erstellt wurde", "dependencies":{ " atob":"^2.0.3", "body-parser":"^1.15.2", "btoa":"^1.1.2", "dotenv":"^4.0.0", "express":" ^4.10.2", "mongoose":"^4.13.7" }, "main":"index.js", "scripts":{ "start":"node index.js" }, "engines":{ "Knoten":"4.8.4" }}
Führen Sie „npm install“ aus, um alle erforderlichen Abhängigkeiten zu installieren.
Sobald alle unsere Abhängigkeiten eingerichtet sind, müssen wir eine Verbindung zu unserem freigegebenen MongoDB-Cluster herstellen. Erstellen Sie eine .env-Datei im Stammverzeichnis des Projekts und fügen Sie ihr die Verbindungszeichenfolge hinzu. Sie können die Verbindungszeichenfolge auf der Seite "Clusterdetails" auf der Registerkarte "Übersicht" in der ScaleGrid-Konsole abrufen.
connectionString=mongodb://user:password@devservers
Bevor wir mit dem Schreiben von Code beginnen, empfiehlt es sich, den App-Fluss zu visualisieren, damit wir ein gutes Verständnis dafür haben, wie der Kürzungsprozess funktioniert. Hier ist ein Diagramm, das den Prozess der URL-Verkürzung zeigt:
Hier ist ein Diagramm, das den Weiterleitungsprozess zeigt, wenn eine verkürzte URL besucht wird:
Da wir nun den gesamten Prozess visualisiert haben, ist es an der Zeit, die obigen Flussdiagramme in Code zu übersetzen.
-
Anwendung initialisieren
Bevor wir mit dem Schreiben der Geschäftslogik beginnen, müssen wir unsere Anwendung mit unseren Knotenmodulen initialisieren und einen Server einrichten.
Lade .env-Dateien nur im Entwicklermodus. Da die Demoanwendung auf Heroku gehostet wird, wurde aus dem Heroku-Dashboard eine Umgebungsvariable erstellt, die dort bereits die Verbindungszeichenfolge enthält:
if(process.env.NODE_ENV !=='production') { require('dotenv').load();}
Anwendungsinitialisierung, Server- und Middleware-Setup. Beachten Sie, dass wir auch die Verbindungszeichenfolge aus der Umgebungsvariablen erhalten:
var express =require('express'), bodyParser =require('body-parser'), app =express(), http =require('http').Server(app), mongoose =require('mongoose '), btoa =require('btoa'), atob =require('atob'), Promise, connectionString =process.env.connectionString, port =process.env.PORT || 8080;http.listen(port, function() { console.log('Server gestartet. Listening on *:' + port);});app.use(express.static('public'));app.use( bodyParser.urlencoded({ erweitert:wahr}));
Basisroute zum Laden des Frontends unserer App:
app.get('/', function(req, res) { res.sendFile('views/index.html', { root:__dirname });});
-
Speichern von URLs in MongoDB
Beginnen wir mit der Erstellung der Sammlungsschemata zum Speichern von Daten. Wie oben besprochen, benötigen wir zwei Sammlungen:eine zum Speichern des automatisch inkrementierten Zählers und die andere zum Speichern der URLs.
var countersSchema =new mongoose.Schema({ _id:{ type:String, required:true }, count:{ type:Number, default:0 }});var Counter =mongoose.model('Counter', countersSchema );var urlSchema =new mongoose.Schema({ _id:{type:Number}, url:'', created_at:''});urlSchema.pre('save', function(next) { console.log('running pre-save'); var doc =this; Counter.findByIdAndUpdate({ _id:'url_count' }, { $inc:{ count:1 } }, function(err, counter) { if(err) return next(err); console.log(counter); console.log(counter.count); doc._id =counter.count; doc.created_at =new Date(); console.log(doc); next(); });});var URL =mongoose.model('URL', urlSchema);
Der obige Code erstellt die beiden Sammlungen und richtet unsere Datenbank zum Speichern dieser Sammlungen ein. Wir verwenden auch einen Pre-Save-Hook für das URL-Schema, da wir den Zähler automatisch erhöhen und Datum und Uhrzeit der URL-Erstellung protokollieren müssen.
Als nächstes müssen wir sicherstellen, dass wir unsere Anwendung neu starten und alle vorherigen Einträge gelöscht werden. Nach dem Zurücksetzen initialisieren wir unseren Zähler mit einem Startwert von 10.000, um den URL-Kürzungsprozess einzurichten. Sie können mit einem beliebigen Wert beginnen. Dies wurde zufällig ausgewählt und wird automatisch um den Wert eins erhöht.
promise =mongoose.connect(connectionString, { useMongoClient:true});promise.then(function(db) { console.log('connected!'); URL.remove({}, function() { console. log('URL-Sammlung entfernt'); }) Counter.remove({}, function() { console.log('Counter-Sammlung entfernt'); var counter =new Counter({_id:'url_count', count:10000} ); counter.save(function(err) { if(err) return console.error(err); console.log('counter inserted'); }); });});
Unsere Anwendung ist jetzt bereit, URLs zu akzeptieren und zu kürzen! Lassen Sie uns eine POST-API erstellen, die unser Front-End verwendet, um die URL zu senden:
app.post('/shorten', function(req, res, next) { console.log(req.body.url); var urlData =req.body.url; URL.findOne({url:urlData} , function(err, doc) { if(doc) { console.log('entry found in db'); res.send({ url:urlData, hash:btoa(doc._id), status:200, statusTxt:' OK' }); } else { console.log('Eintrag NICHT in db gefunden, neu speichern'); var url =neue URL({ url:urlData }); url.save(function(err) { if(err) return console.error(err); res.send({ url:urlData, hash:btoa(url._id), status:200, statusTxt:'OK' }); }); } });});
Wie im Flussdiagramm skizziert, überprüfen wir, sobald eine gültige URL empfangen wird, ob sie in der Datenbank vorhanden ist.
Falls gefunden, entschlüsseln wir das entsprechende _id-Feld und geben den Hash zurück. Unser Front-End erstellt die verkürzte URL und präsentiert sie dem Benutzer zur Weiterleitung.
Wenn keine URL gefunden wird, speichern wir ein neues Dokument in der Sammlung. Denken Sie daran, dass jedes Mal, wenn die URL gespeichert wird, ein Pre-Save-Schritt ausgeführt wird. Dadurch wird der Zähler automatisch erhöht und das aktuelle Datum und die aktuelle Uhrzeit protokolliert. Nachdem das Dokument hinzugefügt wurde, senden wir den Hash an unser Front-End, das die verkürzte URL erstellt und dem Benutzer zur Weiterleitung präsentiert.
-
Weiterleitung von Benutzern
Wir sind fast fertig! Nachdem unsere verkürzten URLs erstellt wurden, benötigen wir eine Möglichkeit, den Benutzer umzuleiten, wenn eine verkürzte URL besucht wird.
app.get('/:hash', function(req, res) { var baseid =req.params.hash; var id =atob(baseid); URL.findOne({ _id:id }, function(err , doc) { if(doc) { res.redirect(doc.url); } else { res.redirect('/'); } });});
Der obige Code sucht nach einem Hash in der verkürzten URL, base64 dekodiert ihn, prüft, ob diese ID in der Sammlung vorhanden ist, und leitet den Benutzer entsprechend weiter. Wird keine ID gefunden, wird der Nutzer auf die Homepage des URL-Shorteners umgeleitet.
Front-End-Code finden Sie im GitHub-Repository, das am Ende dieses Beitrags erwähnt wird. Es handelt sich im Wesentlichen um ein Textfeld mit einer Schaltfläche zum Senden der URL an das Back-End und geht über den Rahmen dieses Artikels hinaus.
Weitere URL-Shortener-Verbesserungen
Und wir sind fertig! Wir haben einen einfachen URL-Shortener, der intern verwendet werden kann, um Ihre Links zu vereinfachen. Wenn Sie mehr Schnickschnack hinzufügen möchten, finden Sie hier eine Liste mit Dingen, die Sie zusätzlich implementieren können:
- Besseres Code-Splitting
- Besserer/benutzerdefinierter Kürzungsalgorithmus für einen kleineren Zeichen-Hash (z. B. base52)
- Teilen von verkürzten URLs in sozialen Medien
- URL-Kopie mit einem Klick
- Benutzerdefinierte Hashes
- Benutzerregistrierung und verknüpfte verkürzte URLs
Der gesamte Code ist hier verfügbar: ScaleGrid URL Shortener Code Samples – Github Eine Demoanwendung wird auf Heroku gehostet:ScaleGrid URL Shortener Demo
Wie immer, wenn Sie etwas Großartiges bauen, twittern Sie uns darüber @scalegridio. Wenn Sie Hilfe beim Hosting für MongoDB® oder Hosting für Redis™* benötigen, wenden Sie sich an [email protected].