短連接咱們或多或少都使用過,所謂短連接就是根據較長的原連接url生成一段較短的連接,訪問短連接能夠跳轉到對應的原連接,這樣作好處在於:1. url更加美觀;2. 便於保存和傳播;3. 某些網站內容發佈有字數限制,短連接能夠節約字數。node
短連接實現的原理很是簡單,能夠歸納爲:git
根據以上思路,咱們本身也能夠分分鐘實現一個短連接生成服務。本文示例使用 node + express + mongodb。github
package.json:web
"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格式是否正確 }
主要用於存放MongoDB的鏈接字符串和短連接的base url。mongodb
config/default.json:數據庫
{ "mongoURI": "mongodb://localhost:27017/url-shorten-service", "baseUrl": "http://localhost:5000" }
config/db.js:express
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;
index.js:npm
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}`); });
咱們須要將原連接和對應短連接保存到數據庫,簡單起見,咱們只須要保存一個短連接編碼,相應的短連接可使用base url和編碼拼接而成。json
models/url.js:api
const mongoose = require('mongoose'); const urlSchema = new mongoose.Schema({ urlCode: String, longUrl: String }); module.exports = mongoose.model('Url', urlSchema);
這是咱們實現的關鍵一步,思路是:用戶傳入一個長連接,咱們首先使用 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;
最後一步很是簡單,當用戶訪問咱們生成的短連接時,咱們根據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/...