如何快速搭建一个短链接服务?
摘要: 很简单的短链接教程。
- 原文:十分钟实现短链接服务(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、微脉、青团社等众多品牌企业。欢迎大家免费试用!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
SpringBoot2.0 整合 RocketMQ ,实现请求异步处理
本文源码:GitHub·点这里 || GitEE·点这里 一、RocketMQ简介 1、架构图片 2、角色分类 (1)、Broker RocketMQ 的核心,接收 Producer 发过来的消息、处理 Consumer 的消费消息请求、消息的持 久化存储、服务端过滤功能等 。 (2)、NameServer 消息队列中的状态服务器,集群的各个组件通过它来了解全局的信息 。类似微服务中注册中心的服务注册,发现,下线,上线的概念。 热备份:NamServer可以部署多个,相互之间独立,其他角色同时向多个NameServer 机器上报状态信息。 心跳机制:NameServer 中的 Broker、 Topic等状态信息不会持久存储,都是由各个角色定时上报并存储到内存中,超时不上报的话, NameServer会认为某个机器出故障不可用。 (3)、Producer 消息的生成者,最常用的producer类就是DefaultMQProducer。 (4)、Consumer 消息的消费者,常用Consumer类DefaultMQPushConsumer收到消息后自动调用传入的处理方法来处理,实时性高...
- 下一篇
关于Python虚拟环境与包管理你应该知道的事
关于Python虚拟环境与包管理你应该知道的事Python拥有大量的第三方库,引用这些库也非常方便,通过pip install就可以将这些第三方库安装到本地Python库文件目录中,然后就可以import到项目中,极大地提升了开发者的编码效率。但这也带来了一个问题:当A项目和B项目同时引用Lib库,而A项目需要Lib版本是1.0,B项目需要Lib的版本是2.0。这样在使用pip install命令将Lib直接安装到本地全局环境中就会发生冲突,有可能会导致A和B的运行环境无法同时得到满足而运行失败。 于是虚拟环境(virtualenv)就出现了。它的核心思想就是为每个项目提供独立的运行环境,这样不同的项目依赖库就不会冲突。 0x00 使用venv+pip1、创建venv安装虚拟环境也非常简单,可以使用venv模块,例如在项目目录中使用Python3创建一个虚拟环境 python3 -m venv venv于是在项目目录中就多了一个venv的文件目录。这个目录就是该项目的虚拟环境。 要使用虚拟环境就必须激活 source venv/bin/activate然后在命令行中就会出现 (venv...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长