摘要: 很簡單的短鏈接教程。
- 原文:十分鍾實現短鏈接服務(Node + Express + MongoDB)
- 作者:MudOnTire
Fundebug經授權轉載,版權歸原作者所有。
短鏈接我們或多或少都使用過,所謂短鏈接就是根據較長的原鏈接url生成一段較短的鏈接,訪問短鏈接可以跳轉到對應的原鏈接,這樣做好處在於:1. url更加美觀;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', async (req, res, 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;
測試一下:
訪問短鏈接:
這樣,一個簡單的短鏈接生成服務就完成了,往往在我們看來很神奇的技術其實背后的原理和實現很簡單,希望本文對大家有所啟發。
最后,推薦大家使用Fundebug,一款很好用的BUG監控工具~
本文Demo地址:https://github.com/MudOnTire/url-shortener-service
關於Fundebug
Fundebug專注於JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了20億+錯誤事件,付費客戶有陽光保險、核桃編程、荔枝FM、掌門1對1、微脈、青團社等眾多品牌企業。歡迎大家免費試用!