如何使用Node.js、Express和MongoDB构建一个自定义URL缩短器
长期以来,使用链接或URL一直是网上冲浪的规范。有时我们需要在社交媒体上宣传我们的业务。长的URL链接不是发布这些链接的最佳方式,尤其是在社交媒体上。这样做将有助于你用提供的链接推广你的产品或任何服务。
URL缩短工具的好处是在帮助推动流量回流到你的网站。
在本教程中,我们将使用Node.js建立一个URL缩短器服务。
前提条件
- 对[JavaScript]编程语言有基本了解。
- 对[Node.js]和[Express]框架有基本了解。
- 在你的系统中安装[Postman]HTTP API客户端。
- 一个文本编辑器,最好是[VS Code]。
- 在你的系统上安装[MongoDB]数据库服务器。
设置项目
创建一个名为URL-Shortener-Service 的文件夹,并在你喜欢的IDE上打开它。我将在这里使用VS Code。进入该文件夹,输入npm init ,为我们的项目生成一个初始的package.json 。
这个命令将需要一些提示,要跳过这一点,你可以使用npm init -y 。我们的项目将使用来自npm注册表的各种npm包。
这些npm包将包括。
-
express:Express是Node.js的一个后端网络应用框架,用于构建网络应用和API。 -
mongoose:Mongoose是MongoDB的一个异步数据库驱动或对象数据映射器。它负责连接到数据库并执行查询操作。 -
short-id:short-id模块为我们的URL创建用户友好和独特的ID。 -
valid-url:: 这是一个验证所有发送到API的URL的模块。 -
nodemon: nodemon包将作为一个开发依赖项被安装。它将通过在任何文件发生变化时自动重启服务器来不断监控我们的应用程序。
接下来,我们现在需要下载这些包。
在你的终端上运行以下命令来下载它们。
npm install express mongoose shortid valid-url
这将下载node_modules 文件夹中的命名包,并将依赖关系更新到package.json 文件中。
注意:
nodemon是一个开发依赖项。要安装它,请运行命令npm install --save-dev nodemon。
设置Express服务器
在我们的URL-Shortener-Service 文件夹中,创建一个名为server.js 的文件。
然后下面是启动Express服务器的初始代码。
// import express package(commonJS syntax)
const express = require('express')
// instatiate the express app
const app = express()
const PORT = process.env.PORT || 5000
// Listen for incoming requests
app.listen(PORT, () => console.log(`server started, listening PORT ${PORT}`))
这段启动代码导入了Express包。app = express() 创建了一个我们应用程序的实例。在我们的应用程序中,我们需要监听传入的请求。
app.listen 需要一个端口号和一个回调函数,在连接成功后被调用。
在 "db.config.js "中配置MongoDB连接
我们将使用我们通过npm安装的mongoose 包作为数据库驱动。为了配置数据库,在我们的URL-Shortener-Service 文件夹内创建一个config 文件夹。在config 文件夹内,添加一个名为db.config.js 的文件。
这是要添加以下数据库连接代码的文件。
// import mongoose package
const mongoose = require('mongoose')
// declare a Database string URI
const DB_URI = 'mongodb://localhost:27017/urlshortener'
// establishing a database connection
mongoose.connect(DB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
})
const connection = mongoose.connection
// export the connection object
module.exports = connection
const mongoose = require('mongoose') 从node_modules 文件夹中导入mongoose 包。为了在我们的MongoDB数据库上启动一个连接,我们需要一个数据库连接端口。这被命名为DB_URI 连接字符串,urlshortener 作为数据库名称。
mongoose.connect() 是一个方法,它接受DB_URI 和一个选项对象来建立连接。module.exports 输出的连接将在我们的index.js 服务器条目文件中添加。
URL详细信息的数据库模型
当使用mongoose时,模型是使用Schema 接口定义的。模式将允许我们定义存储在每个文件中的所有字段,以及验证或默认值。
然后,模式将使用mongoose.model() 方法被转化为模型。模型是我们用来寻找、创建、更新和删除给定类型的文档的东西。
为了创建我们的模型,创建一个名为models 的文件夹。
在这个文件夹内,添加一个名为UrlModel.js 的文件,并添加以下代码。
const mongoose = require('mongoose')
// instantiate a mongoose schema
const URLSchema = new mongoose.Schema({
urlCode: String,
longUrl: String,
shortUrl: String,
date: {
type: String,
default: Date.now
}
})
// create a model from schema and export it
module.exports = mongoose.model('Url', URLSchema)
为了创建一个模型,我们需要通过导入mongoose npm包来创建一个模式接口。mongoose.Schema 方法被实例化,以定义与和对象参数。这个对象需要我们的MongoDB文档将存储的值。
这些值包括。
-
urlCode是一个字符串属性,将存储与每个URL相关的唯一ID。 -
longUrl是默认的URL,我们需要将其缩短。 -
属性
shortUrl是将被生成的实际短网址。 -
date属性有一个默认的属性,一旦model在数据库中被实例化就会被创建。
定义路由
我们的路由将在一个单独的文件夹上。在URL-Shortener-Service 文件夹内,创建一个名为routes 的文件夹。
我们将创建两个路由文件,名为。
-
url.js:这将是一个POST路由,它接收带有长URL的传入请求,创建短URL并将其插入数据库中。在routes文件夹中导航并创建一个名为url.js的文件。 -
redirect.js:这是一个用于我们的URL重定向的GET。它获取短网址并将其重定向到浏览器中的实际长网址。要添加这个文件,请在routes文件夹中创建一个名为redirect.js的单独文件。
url.js POST路线
现在,让我们来创建POST路由。
在url.js 文件中添加以下代码。
// packages needed in this file
const express = require('express')
const validUrl = require('valid-url')
const shortid = require('shortid')
// creating express route handler
const router = express.Router()
// import the Url database model
const Url = require('../models/Url')
// @route POST /api/url/shorten
// @description Create short URL
// The API base Url endpoint
const baseUrl = 'http:localhost:5000'
router.post('/shorten', async (req, res) => {
const {
longUrl
} = req.body // destructure the longUrl from req.body.longUrl
// check base url if valid using the validUrl.isUri method
if (!validUrl.isUri(baseUrl)) {
return res.status(401).json('Invalid base URL')
}
// if valid, we create the url code
const urlCode = shortid.generate()
// check long url if valid using the validUrl.isUri method
if (validUrl.isUri(longUrl)) {
try {
/* The findOne() provides a match to only the subset of the documents
in the collection that match the query. In this case, before creating the short URL,
we check if the long URL was in the DB ,else we create it.
*/
let url = await Url.findOne({
longUrl
})
// url exist and return the respose
if (url) {
res.json(url)
} else {
// join the generated short code the the base url
const shortUrl = baseUrl + '/' + urlCode
// invoking the Url model and saving to the DB
url = new Url({
longUrl,
shortUrl,
urlCode,
date: new Date()
})
await url.save()
res.json(url)
}
}
// exception handler
catch (err) {
console.log(err)
res.status(500).json('Server Error')
}
} else {
res.status(401).json('Invalid longUrl')
}
})
module.exports = router
我们的url.js 文件的代码演练。
重定向路由
现在我们已经创建了一个创建短网址的POST路由,我们需要执行一个重定向,使我们的短网址指向实际的网址。这是对我们的Node.js API的一个GET请求查询。
下面是要添加到redirect.js 文件中的代码。
const express = require('express')
const router = express.Router()
const Url = require('../models/Url')
// : app.get(/:code)
// @route GET /:code
// @description Redirect to the long/original URL
router.get('/:code', async (req, res) => {
try {
// find a document match to the code in req.params.code
const url = await Url.findOne({
urlCode: req.params.code
})
if (url) {
// when valid we perform a redirect
return res.redirect(url.longUrl)
} else {
// else return a not found 404 status
return res.status(404).json('No URL Found')
}
}
// exception handler
catch (err) {
console.error(err)
res.status(500).json('Server Error')
}
})
module.exports = router
现在我们来了解一下上面的代码。要在express中设置一个路由,我们需要导入express 模块并初始化express.Router() 方法。这个API路由需要我们创建的数据库模型来保存将生成的短网址。
为了实现这一点,我们需要导入valid-url 进行验证,并导入short-id ,它将为我们的短网址创建唯一的ID。我们的localhost应用程序将使用一个基本的URL(baseUrl 变量)作为http:\\localhost:5000 。
我们现在需要从我们的请求体中提取longUrl ,通过执行方法validUrl.isUri(baseUrl) ,用valid-url 包来验证ID,并将URL作为参数传递。
如果URL是有效的,我们使用const urlCode = shortid.generate() ,生成一个短代码,并在保存到数据库之前将其附加到我们的基本URL。这个过程是异步的,这就是为什么我们使用承诺或async-await语法。
最后的 "index.js "条目文件
const express = require("express")
const app = express()
// Database config
const connection = require('./config/db')
connection.once('open', () => console.log('DB Connected'))
connection.on('error', () => console.log('Error'))
// Routes Config
app.use(express.json({
extended: false
})) //parse incoming request body in JSON format.
app.use('/', require('./routes/redirect'))
app.use('/api/url', require('./routes/url'))
//Listen for incoming requests
const PORT = process.env.PORT || 5000
app.listen(PORT, console.log(`server started, listening PORT ${PORT}`))
为了使我们的路由工作,我们必须使用一个中间件模式,如Express。在应用程序的请求-响应循环中,中间件函数可以访问请求(req)和响应对象(res)。这就解释了app.use() 的方法。
第一个中间件允许我们的应用程序以JSON格式解析传入的请求数据格式。app.use('/', require('./routes/redirect')) 是将配置重定向路由的基础URI。
在我们的POST路由中,基本URL是/api/url ,中间件是app.use('/api/url', require('./routes/url')) 。接下来,我们需要在Postman中测试该应用程序。
在Postman中的一个工作演示

请在我的GitHub资源库中查看源代码。
总结
拥有一个链接管理平台将使你能够利用分享、管理和分析链接的力量。互联网上每年有数十亿的链接被创建,URL缩短器服务在社会媒体营销中尤其有用。
在本教程中,我们使用Node.js和MongoDB作为数据库创建了一个简单的URL缩短器服务。我希望你觉得这个教程很有帮助。