


Detailed explanation of the short link service implemented by Nodejs+Nest
This article will introduce to you the method of implementing short link service based on the Node framework Nest. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.
Recommended study: "nodejs tutorial"
We can see all kinds of strange short links in our daily life. Every time I click to jump, I feel magical. How does this short link guide users to the correct page?
Principle of short chain
The principle of short chain is to make a short blog longer, so how can this short string be turned into a long string of links? Is it relying on some magical encryption algorithm? No, we only need to rely on the key/value mapping relationship to easily achieve this seemingly magical making short work long.
With a picture, everyone can clearly see the entire process of accessing the short link.
First, we will have a long link. Through the processing of the short link service, a URL with only one layer of directories will usually be output. Then we can process the obtained URL. distribution.
Then we get to the user side. After the user clicks on the short link, the first thing they reach is not the target page, but the short link service.
The short link service will intercept the pathname on the link and use it as a key to find the corresponding value in the mapping relationship.
If the corresponding value cannot be found, it means that the short link does not exist or has expired; if the query is successful, the short link service will directly 302 to the target link in the value to complete a short link access. .
Specific implementation
Materials: Fast-NestScaffolding, Redis
The entire implementation is split into 3 parts:
① Receive long link
@Post('/createUrl') async createUrl( @Body('url') url: string, @Body('type') type: string, ) { const shortUrl = await this.shorturlService.createUrl(url, type); return { shortUrl, }; }
Create a createUrl
interface in the service, receive the url
and type
fields, and add It is passed into shorturlService
, waits for the short link to be generated and then outputs it.
② Generate shortKey
async createUrl(url: string, type: string = 'normal') { const urlKey = await this.handleUrlKey(); const dataStr = JSON.stringify({ url, type }); await this.client.set(urlKey, dataStr, type === 'permanent' ? -1 : 300); return `${Config.defaultHost}/${urlKey}`; } private async handleUrlKey(count?: number): Promise<string> { const _count = count || 1; const maxCount = Config.maxRetryTimes; if (_count >= maxCount) throw new HttpException('超过重试次数,请重新生成链接', HttpStatus.INTERNAL_SERVER_ERROR); const urlKey: string = Math.random().toString(36).slice(-4); const _url = await this.client.get(urlKey); if (_url) { return await this.handleUrlKey(_count + 1); } return urlKey; }
First get a 4-digit random string through Math.random().toString(36).slice(-4)
, this will Pathname as a short link.
Before mapping, we need to judge its uniqueness. Although it is unlikely, we still need to prevent problems such as short chain coverage. The solution of this service is to retry generation. If the short chain value is unfortunately repeated, it will enter the retry branch. The service will have a built-in number of retries. If the number of retries exceeds the configured number of words, this conversion will return failure. .
In addition to url
, the createUrl
method also accepts a type
field, which involves the characteristics of special short links. Our short links have three modes:
- normal - normal short links will expire within the specified time
- once - one-time short links will expire within the specified time, It will automatically expire after being accessed
- permanent - long-term short link will not automatically expire and only accepts manual deletion
After generating urlKey
, it will be the same as type
is converted into a string and stored in redis, and the spliced short link is output.
③ Receive the short link and complete the target redirection
@Get('/:key') @Redirect(Config.defaultIndex, 302) async getUrl( @Param('key') key: string, ) { if (key) { const url = await this.shorturlService.getUrl(key); return { url } } } // this.shorturlService.getUrl async getUrl(k: string) { const dataStr = await this.client.get(k); if (!dataStr) return; const { url, type } = JSON.parse(dataStr); if (type === 'once') { await this.client.del(k); } return url; }
The user side will get a link similar to http://localhost:8000/s/ku6a
, after clicking It is equivalent to sending a GET request to the short link service.
After receiving the request, the service obtains the value of the key field in the link, which is the string ku6a
, and uses it to find the mapping relationship in Redis.
There are two branches here. One is that the relevant value cannot be queried in Redis. The service thinks that the short link has expired and will return directly because getUrl
returns a null value and redirects. The decorator will redirect this request to the default target link.
If the relevant value is successfully found in Redis, the url
and type
fields will be read. If type is once, it means that this is a one-time use. The link will actively trigger the deletion method and eventually return the target link.
Extra functions
Use the log system to output reports
When using short links, there is a high probability that relevant data statistics will be needed. How to collect data without using a database? What about statistics?
In this service, we can complete the report of short-link access on the same day by scanning the landing log file.
When generating short links, add the urlID field for statistical differentiation and actively output logs, as follows:
async createUrl(url: string, type: string = 'normal') { const urlKey = await this.handleUrlKey(); const urlID = UUID.genV4().toString(); const dataStr = JSON.stringify({ urlID, url, type }); this.myLogger.log(`createUrl**${urlID}`, 'createUrl', false); await this.client.set(urlKey, dataStr, type === 'permanent' ? -1 : 300); return `${Config.defaultHost}/${urlKey}`; }
然后在用户点击短链接时获取该短链接的urlID字段,并主动输出日志,如下:
async getUrl(k: string) { const dataStr = await this.client.get(k); if (!dataStr) return; const { url, type, urlID } = JSON.parse(dataStr); if (type === 'once') { await this.client.del(k); } this.myLogger.log(`getUrl**${urlID}`, 'getUrl', false); return url; }
这么一来我们将能够在服务的logs目录中获得类似这样的日志:
2021-04-25 22:31:03.306 INFO [11999] [-] createUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:38.323 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:39.399 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:40.281 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:40.997 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:41.977 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:42.870 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:43.716 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:44.614 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf
之后我们只需要以createUrl
的日志为索引,对getUrl
类型的日志进行计数,即可完成链接与点击数的报表,如果还需要其他维度的报表只需要在输出日志的时候带上即可,或者修改日志中间件中的日志范式。
使用方式
根据上述的流程,笔者写了一个比较简易的短链服务,大家可以开箱即用。
具体启动方式
首先请确保有可用的redis,否则无法顺利启动服务。
git clone https://github.com/mykurisu/shorturl.git cd shorturl npm install npm start
可用配置修改
与短链相关的配置收束在根目录的config.ts
中。
serverConfig: { port: 8000, }, redis: { port: 6379, host: '0.0.0.0', db: 0, }, cacheType: 'redis', defaultHost: 'http://localhost:8000/s', defaultIndex: 'http://localhost:8000/defaultIndex',
配置 | 默认值 | 配置用途 |
---|---|---|
serverConfig.port | 8000 | 服务启动端口 |
redis.port | 6379 | redis端口 |
redis.host | 0.0.0.0 | redis服务地址 |
redis.db | 0 | redis具体储存库表 |
cacheType | redis | 短链储存模式,接受memory/redis |
maxRetryTimes | 5 | 生成短链接最大重试次数 |
defaultHost | http://localhost:8000/s | 短链接前缀 |
defaultIndex | http://localhost:8000/defaultIndex | 短链接失效后重定向地址 |
内置接口
接口路由 | 请求方式 | 接口参数 | 接口用途 |
---|---|---|---|
/s/createUrl | POST | url: string, type?: string | 短链接生成接口 |
/s/deleteUrl | POST | k: string | 删除短链接接口 |
/s/:key | GET | none | 目标链接获取 |
拓展
① 储存降级策略
shorturl是有本地储存方案的,也就是说我们是可以监听Redis的状态,如果断开连接时就临时将数据储存到内存中,以达到服务降级的目的。当然我们也可以直接使用内存来储存短链内容,在config.ts
配置中可以进行更改。
② 不仅仅是短链接服务
让我们脱离短链接这个束缚,其实shorturl本身已经是一个微型存储服务了,我们完全可以进行二次开发,输出更多的模块以支撑更多样的业务。
小结
整个短链接服务其实非常简单,麻烦的是服务的搭建,也就是迈出的第一步。笔者也是在无数次最初一步中挣扎,最终积累了fast-nest这么一个脚手架,希望能帮助到有同样境遇的同学。
另外,附上本文的服务源码 -- shorturl(欢迎大家Star)
更多编程相关知识,请访问:编程教学!!
The above is the detailed content of Detailed explanation of the short link service implemented by Nodejs+Nest. For more information, please follow other related articles on the PHP Chinese website!

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Dreamweaver CS6
Visual web development tools

WebStorm Mac version
Useful JavaScript development tools

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),
