MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come creare un URL Shortener con Node.js e MongoDB

In questo post, ti mostreremo come creare un servizio di abbreviazione degli URL come bit.ly o goo.gl utilizzando Express.js (Node.js) e MongoDB. Ecco una demo del prodotto finale che realizzeremo tramite la nostra piattaforma di hosting MongoDB.

Come funziona un accorciatore di URL?

A un livello molto alto, l'abbreviatore di URL funziona prendendo un URL inserito e creando una versione relativamente abbreviata semplificata in un formato facile da condividere. L'hash abbreviato verrà generato codificando in base un contatore con incremento automatico e crea un hash minimo di tre caratteri che aumenta all'aumentare del numero di URL archiviati.

Quando viene visitata la versione abbreviata dell'URL, il servizio decodificherà l'hash per recuperare l'URL originale memorizzato in MongoDB e quindi reindirizzare l'utente ad esso.

Per iniziare

Ecco un elenco delle tecnologie che utilizzeremo per creare l'abbreviatore di URL in questo tutorial:

  • Express.js (backend Node.js)

    Un framework di applicazioni Web per Node.js. Lo useremo per creare un'API per abbreviare gli URL e reindirizzare gli utenti all'URL originale.

  • MongoDB (memorizzazione di URL)

    Un database NoSQL perfetto per questa applicazione. Fornisce una progettazione dello schema flessibile ed è facile da iniziare. In questo tutorial utilizzeremo un cluster MongoDB condiviso su ScaleGrid. La configurazione richiede meno di 5 minuti e puoi creare una prova gratuita di 30 giorni qui per iniziare.

  • HTML, CSS, JavaScript (front-end)

    HTML, CSS e JavaScript verranno utilizzati per creare il front-end dell'applicazione che i tuoi utenti utilizzeranno per abbreviare gli URL.

Come creare un URL shortener con Node.js e MongoDBClick To Tweet

Esercitazione sull'abbreviazione di URL

  1. Imposta la struttura del database di MongoDB

    Iniziamo creando un cluster MongoDB condiviso su ScaleGrid. Questo è il modo più semplice per creare un cluster veloce, ma puoi anche installare MongoDB sul tuo computer e iniziare da lì.

    Una volta creato il cluster, ti verrà fornita una stringa di connessione che può essere copiata con un solo clic dalla pagina Dettagli del cluster. Avremo bisogno di questa stringa per connetterci al cluster dalla nostra applicazione. Ricorda, non condividere mai la tua stringa di connessione con nessuno.

    Avremo bisogno di due raccolte per l'abbreviazione di URL:

    • Raccolta 1

      Una raccolta in cui memorizzare l'URL e l'ID generato dinamicamente:

    • Raccolta 2

      Una raccolta per mantenere il contatore che verrà incrementato automaticamente quando un nuovo URL viene archiviato nella raccolta precedente. Viene creato un nuovo documento nella raccolta precedente con questo contatore appena incrementato:

    È importante notare che non memorizziamo gli hash da nessuna parte nel database. L'hash sarà codificato in base e decodificato dinamicamente con l'algoritmo generale che risulterà nell'ID univoco memorizzato nella prima raccolta. Questo ID ci recupererà quindi l'URL originale a cui l'utente reindirizzerà.

    Per questo tutorial, utilizzeremo il comune meccanismo di codifica e decodifica base64 per generare il nostro hash abbreviato unico. Per ulteriori informazioni sulla codifica/decodifica delle stringhe utilizzando base64, consulta il seguente documento Web MDN.

  2. Configura il backend di Express.js

    Ecco un elenco di dipendenze necessarie per configurare il nostro back-end Node.js:

    • express (app di base)
    • body-parser (componente aggiuntivo per l'analisi dei dati inviati tramite richieste HTTP)
    • btoa (codifica base64)
    • atob (decodifica base64)
    • dotenv (memorizzazione della stringa di connessione in un file .env per scopi di sviluppo)
    • mongoose (adattatore per MongoDB su Node.js)

    Ecco una versione di esempio di package.json che puoi utilizzare per configurare l'app:

    {
      "name": "sg-url-shortener",
      "version": "1.0.0",
      "description": "A simple URL shortener built with Node.js and MongoDB",
      "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": {
        "node": "4.8.4"
      }
    }
    

    Esegui "npm install" per installare tutte le dipendenze richieste.

    Una volta configurate tutte le nostre dipendenze, dobbiamo connetterci al nostro cluster MongoDB condiviso. Crea un file .env nella radice del progetto e aggiungi la stringa di connessione. Puoi ottenere la stringa di connessione dalla pagina Dettagli cluster nella scheda Panoramica della console ScaleGrid.

    connectionString=mongodb://user:password@devservers

    Prima di iniziare a scrivere codice, è buona norma visualizzare il flusso dell'app in modo da avere una buona comprensione di come funzionerà il processo di abbreviazione. Ecco un diagramma che mostra il processo di abbreviazione degli URL:

    Ecco un diagramma che mostra il processo di reindirizzamento quando viene visitato un URL abbreviato:

    Ora che abbiamo visualizzato l'intero processo, è il momento di tradurre i diagrammi di flusso sopra in codice.

  3. Inizializzazione dell'applicazione

    Prima di iniziare a scrivere la logica aziendale, dobbiamo inizializzare la nostra applicazione con i nostri moduli di nodo e configurare un server.

    Carica i file .env solo in modalità dev. Poiché l'applicazione demo è ospitata su Heroku, è stata creata una variabile di ambiente dalla dashboard di Heroku che contiene già la stringa di connessione lì:

    if(process.env.NODE_ENV !== 'production') {
        require('dotenv').load();
    }

    Inizializzazione dell'applicazione, configurazione del server e del middleware. Nota che stiamo ottenendo anche la stringa di connessione dalla variabile di ambiente:

    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 Started. Listening on *:' + port);
    });
    
    app.use(express.static('public'));
    app.use(bodyParser.urlencoded({
        extended: true
    }));

    Percorso base per caricare il front-end della nostra app:

    app.get('/', function(req, res) {
        res.sendFile('views/index.html', {
            root: __dirname
        });
    });
    
  4. Memorizzazione degli URL in MongoDB

    Iniziamo creando gli schemi di raccolta per la memorizzazione dei dati. Come discusso in precedenza, abbiamo bisogno di due raccolte:una per la memorizzazione del contatore a incremento automatico e l'altra per la memorizzazione degli URL.

    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);
    

    Il codice sopra crea le due raccolte e imposta il nostro database per la memorizzazione di queste raccolte. Utilizziamo anche un hook di pre-salvataggio per lo schema dell'URL poiché è necessario incrementare automaticamente il contatore e registrare la data e l'ora in cui è stato creato l'URL.

    Successivamente, dobbiamo assicurarci di avviare la nostra applicazione da zero e che tutte le voci precedenti vengano eliminate. Una volta ripristinato, inizializzeremo il nostro contatore con un valore iniziale di 10.000 per impostare il processo di accorciamento degli URL. Puoi iniziare con qualsiasi valore. Questo è stato scelto a caso e si aumenterà automaticamente di un valore di uno.

    promise = mongoose.connect(connectionString, {
        useMongoClient: true
    });
    
    promise.then(function(db) {
        console.log('connected!');
        URL.remove({}, function() {
            console.log('URL collection removed');
        })
        Counter.remove({}, function() {
            console.log('Counter collection removed');
            var counter = new Counter({_id: 'url_count', count: 10000});
            counter.save(function(err) {
                if(err) return console.error(err);
                console.log('counter inserted');
            });
        });
    });
    

    La nostra applicazione è ora pronta per iniziare ad accettare e ad abbreviare gli URL! Creiamo un'API POST che il nostro front-end utilizzerà per inviare l'URL:

    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('entry NOT found in db, saving new');
                var url = new 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'
                    });
                });
            }
        });
    });

    Come descritto nel diagramma di flusso, una volta ricevuto un URL valido, ne controlliamo l'esistenza nel database.

    Se trovato, decodifichiamo il campo _id corrispondente e restituiamo l'hash. Il nostro front-end costruisce l'URL abbreviato e lo presenta all'utente per il reindirizzamento.

    Se non viene trovato alcun URL, salviamo un nuovo documento nella raccolta. Ricorda, un passaggio di pre-salvataggio viene eseguito ogni volta che l'URL viene salvato. Questo aumenterà automaticamente il contatore e registrerà la data e l'ora correnti. Dopo che il documento è stato aggiunto, inviamo l'hash al nostro front-end che costruisce l'URL abbreviato e lo presenta all'utente per il reindirizzamento.

  5. Reindirizzamento degli utenti

    Abbiamo quasi finito! Una volta creati i nostri URL abbreviati, abbiamo bisogno di un modo per reindirizzare l'utente quando viene visitato un URL abbreviato.

    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('/');
            }
        });
    });

    Il codice sopra cerca un hash nell'URL abbreviato, base64 lo decodifica, controlla se quell'ID è presente nella raccolta e reindirizza l'utente di conseguenza. Se non viene trovato alcun ID, l'utente viene reindirizzato alla home page dell'abbreviatore di URL.

    Per il codice front-end, controlla il repository GitHub menzionato alla fine di questo post. È essenzialmente una casella di testo con un pulsante per inviare l'URL al back-end ed è fuori dallo scopo di questo articolo.

Altri miglioramenti per l'abbreviazione di URL

E abbiamo finito! Abbiamo un semplice accorciatore di URL che può essere utilizzato internamente per semplificare i tuoi collegamenti. Se desideri aggiungere più campanelli e fischietti, ecco un elenco di cose che puoi implementare ulteriormente:

  • Migliore suddivisione del codice
  • Algoritmo di accorciamento migliore/personalizzato per un hash di caratteri più piccolo (ad es. base52)
  • Condivisione di URL abbreviati sui social media
  • Copia URL con un clic
  • Hash personalizzati
  • Registrazione utente e associa URL abbreviati

L'intero codice è disponibile qui: ScaleGrid URL Shortener Code Samples – Github Un'applicazione demo è ospitata su Heroku:ScaleGrid URL Shortener Demo

Come sempre, se costruisci qualcosa di fantastico, scrivici un tweet a riguardo @scalegridio. Se hai bisogno di aiuto con l'hosting per MongoDB® o l'hosting per Redis™*, contattaci all'indirizzo [email protected].