1. 程式人生 > 程式設計 >十分鐘實現短連結服務(Node + Express + MongoDB)

十分鐘實現短連結服務(Node + Express + MongoDB)

短連結我們或多或少都使用過,所謂短連結就是根據較長的原連結url生成一段較短的連結,訪問短連結可以跳轉到對應的原連結,這樣做好處在於:1. url更加美觀;2. 便於儲存和傳播;3. 某些網站內容釋出有字數限制,短連結可以節約字數。

短連結實現的原理非常簡單,可以概括為:

  1. 為每個原連結生成不重複的唯一短連結
  2. 將原連結和對應短連結成對儲存到資料庫
  3. 訪問短連結時,web伺服器將目標重定向到對應的原連結

根據以上思路,我們自己也可以分分鐘實現一個短連結生成服務。本文示例使用 node + express + mongodb。

1. 初始化專案

(1). 安裝如下依賴:

package.json:

"dependencies": {
  "config": "^3.2.2",// 讀取專案配置
  "express": "^4.17.1",// web伺服器
  "mongoose": "^5.6.9",// 操作mongodb
  "shortid": "^2.2.14",// 生成不重複的唯一Id
  "valid-url": "^1.0.9" // 判斷url格式是否正確
}
複製程式碼

(2). 增加專案配置:

主要用於存放MongoDB的連線字串和短連結的base url。

config/default.json:

{
  "mongoURI": "mongodb://localhost:27017/url-shorten-service"
,"baseUrl": "http://localhost:5000" } 複製程式碼

(3). 增加MongoDB連線方法

config/db.js:

const mongoose = require('mongoose');
const config = require('config');
const db = config.get('mongoURI');

const connectDB = async () => {
  try {
    await mongoose.connect(db,{
      useNewUrlParser: true
    });
    console.log(`MongoDB Connected to: ${db}
`); } catch (error) { console.error(error.message); process.exit(1); } } module.exports = connectDB; 複製程式碼

(4). 啟動express:

index.js:

const express = require('express');
const connectDB = require('./config/db');

const app = express();

// 連線MongoDB
connectDB();

app.use(express.json({
  extended: false
}));

// 路由,稍後設定
app.use('/',require('./routes/index'));
app.use('/api/url',require('./routes/url'));

const port = 5000;

app.listen(port,() => {
  console.log(`Server running on port ${port}`);
});
複製程式碼

2. 定義資料庫模型

我們需要將原連結和對應短連結儲存到資料庫,簡單起見,我們只需要儲存一個短連結編碼,相應的短連結可以使用base url和編碼拼接而成。

models/url.js:

const mongoose = require('mongoose');

const urlSchema = new mongoose.Schema({
  urlCode: String,longUrl: String
});

module.exports = mongoose.model('Url',urlSchema);
複製程式碼

3. 生成短連結編碼

這是我們實現的關鍵一步,思路是:使用者傳入一個長連結,我們首先使用 valid-url 判斷傳入的url是否合法,不合法則返回錯誤,如果合法我們在資料庫中搜索是否有該長連結的記錄,如果有則直接返回該條記錄,如果沒有則生成一條新記錄,並生成對應的短連結。藉助於 shortId,我們可以很方便的生成一個不重複的唯一編碼。

routes/url.js:

const epxress = require("express");
const router = epxress.Router();
const validUrl = require('valid-url');
const shortId = require('shortid');
const config = require('config');
const Url = require('../models/url');

router.post('/shorten',async (req,res,next) => {
  const { longUrl } = req.body;
  if (validUrl.isUri(longUrl)) {
    try {
      let url = await Url.findOne({ longUrl });
      if (url) {
        res.json({
          shortUrl: `${config.get('baseUrl')}/${url.urlCode}`
        });
      } else {
        const urlCode = shortId.generate();
        url = new Url({
          longUrl,urlCode
        });
        await url.save();
        res.json({
          shortUrl: `${config.get('baseUrl')}/${urlCode}`
        });
      }
    } catch (error) {
      res.status(500).json('Server error');
    }
  } else {
    res.status(401).json('Invalid long url');
  }
});

module.exports = router;
複製程式碼

4. 訪問短連結跳轉到原連結

最後一步非常簡單,當使用者訪問我們生成的短連結時,我們根據url中的短連結編碼查詢到對應記錄,如果存在對應記錄我們使用express的res.redirect方法將訪問重定向至原連結,如果不存在則返回錯誤。

routes/index.js

const epxress = require("express");
const router = epxress.Router();
const Url = require('../models/url');

router.get('/:code',next) => {
  try {
    const urlCode = req.params.code;
    const url = await Url.findOne({ urlCode });
    if (url) {
      // 重定向至原連結
      res.redirect(url.longUrl);
    } else {
      res.status(404).json("No url found");
    }
  } catch (error) {
    res.status(500).json("Server error");
  }
});

module.exports = router;
複製程式碼

測試一下:

send request

訪問短連結:

redirect

這樣,一個簡單的短連結生成服務就完成了,往往在我們看來很神奇的技術其實背後的原理和實現很簡單,希望本文對大家有所啟發。

最後,推薦大家使用Fundebug,一款很好用的BUG監控工具~

本文Demo地址:github.com/MudOnTire/u…