十分钟实现短连接服务(Node + Express + MongoDB)

短连接咱们或多或少都使用过,所谓短连接就是根据较长的原连接url生成一段较短的连接,访问短连接能够跳转到对应的原连接,这样作好处在于:1. url更加美观;2. 便于保存和传播;3. 某些网站内容发布有字数限制,短连接能够节约字数。node

短连接实现的原理很是简单,能够归纳为:git

  1. 为每一个原连接生成不重复的惟一短连接
  2. 将原连接和对应短连接成对保存到数据库
  3. 访问短连接时,web服务器将目标重定向到对应的原连接

根据以上思路,咱们本身也能够分分钟实现一个短连接生成服务。本文示例使用 node + express + mongodb。github

1. 初始化项目

(1). 安装以下依赖:

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格式是否正确
}

(2). 增长项目配置:

主要用于存放MongoDB的链接字符串和短连接的base url。mongodb

config/default.json:数据库

{
  "mongoURI": "mongodb://localhost:27017/url-shorten-service",
  "baseUrl": "http://localhost:5000"
}

(3). 增长MongoDB链接方法

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;

(4). 启动express:

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

2. 定义数据库模型

咱们须要将原连接和对应短连接保存到数据库,简单起见,咱们只须要保存一个短连接编码,相应的短连接可使用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);

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;

测试一下:

send request

访问短连接:

clipboard.png

这样,一个简单的短连接生成服务就完成了,每每在咱们看来很神奇的技术其实背后的原理和实现很简单,但愿本文对你们有所启发。

最后,推荐你们使用 Fundebug,一款很好用的BUG监控工具~

本文Demo地址:https://github.com/MudOnTire/...

相关文章
相关标签/搜索