Table of Contents
Principle of short chain
Specific implementation
① Receive long link
② Generate shortKey
③ Receive the short link and complete the target redirection
Extra functions
Use the log system to output reports
使用方式
拓展
① 储存降级策略
② 不仅仅是短链接服务
小结
Home Web Front-end JS Tutorial Detailed explanation of the short link service implemented by Nodejs+Nest

Detailed explanation of the short link service implemented by Nodejs+Nest

Apr 30, 2021 am 10:48 AM
nest nodejs

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.

Detailed explanation of the short link service implemented by Nodejs+Nest

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.

Detailed explanation of the short link service implemented by Nodejs+Nest

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:

@Post('/createUrl')
async createUrl(
    @Body('url') url: string,
    @Body('type') type: string,
) {
    const shortUrl = await this.shorturlService.createUrl(url, type);
    return {
        shortUrl,
    };
}
Copy after login

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(&#39;超过重试次数,请重新生成链接&#39;, 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;
}
Copy after login

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.

@Get(&#39;/:key&#39;)
@Redirect(Config.defaultIndex, 302)
async getUrl(
        @Param(&#39;key&#39;) 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 === &#39;once&#39;) {
        await this.client.del(k);
    }
    return url;
}
Copy after login

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 = &#39;normal&#39;) {
    const urlKey = await this.handleUrlKey();
    const urlID = UUID.genV4().toString();
    const dataStr = JSON.stringify({
        urlID,
        url,
        type
    });
    this.myLogger.log(`createUrl**${urlID}`, &#39;createUrl&#39;, false);
    await this.client.set(urlKey, dataStr, type === &#39;permanent&#39; ? -1 : 300);
    return `${Config.defaultHost}/${urlKey}`;
}
Copy after login

然后在用户点击短链接时获取该短链接的urlID字段,并主动输出日志,如下:

async getUrl(k: string) {
    const dataStr = await this.client.get(k);
    if (!dataStr) return;
    const { url, type, urlID } = JSON.parse(dataStr);
    if (type === &#39;once&#39;) {
        await this.client.del(k);
    }
    this.myLogger.log(`getUrl**${urlID}`, &#39;getUrl&#39;, false);
    return url;
}
Copy after login

这么一来我们将能够在服务的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
Copy after login

之后我们只需要以createUrl的日志为索引,对getUrl类型的日志进行计数,即可完成链接与点击数的报表,如果还需要其他维度的报表只需要在输出日志的时候带上即可,或者修改日志中间件中的日志范式。

使用方式

根据上述的流程,笔者写了一个比较简易的短链服务,大家可以开箱即用。

shorturl(欢迎大家Star⭐️⭐️)

具体启动方式

首先请确保有可用的redis,否则无法顺利启动服务。

git clone https://github.com/mykurisu/shorturl.git

cd shorturl

npm install

npm start
Copy after login

可用配置修改

与短链相关的配置收束在根目录的config.ts中。

serverConfig: {
    port: 8000,
},
redis: {
    port: 6379,
    host: &#39;0.0.0.0&#39;,
    db: 0,
},
cacheType: &#39;redis&#39;,
defaultHost: &#39;http://localhost:8000/s&#39;,
defaultIndex: &#39;http://localhost:8000/defaultIndex&#39;,
Copy after login
配置 默认值 配置用途
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!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot Article Tags

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

The difference between nodejs and tomcat The difference between nodejs and tomcat Apr 21, 2024 am 04:16 AM

The difference between nodejs and tomcat

The difference between nodejs and vuejs The difference between nodejs and vuejs Apr 21, 2024 am 04:17 AM

The difference between nodejs and vuejs

Is nodejs a backend framework? Is nodejs a backend framework? Apr 21, 2024 am 05:09 AM

Is nodejs a backend framework?

What is the difference between npm and npm.cmd files in the nodejs installation directory? What is the difference between npm and npm.cmd files in the nodejs installation directory? Apr 21, 2024 am 05:18 AM

What is the difference between npm and npm.cmd files in the nodejs installation directory?

What are the global variables in nodejs What are the global variables in nodejs Apr 21, 2024 am 04:54 AM

What are the global variables in nodejs

Is nodejs a back-end development language? Is nodejs a back-end development language? Apr 21, 2024 am 05:09 AM

Is nodejs a back-end development language?

Is there a big difference between nodejs and java? Is there a big difference between nodejs and java? Apr 21, 2024 am 06:12 AM

Is there a big difference between nodejs and java?

Which one to choose between nodejs and java? Which one to choose between nodejs and java? Apr 21, 2024 am 04:40 AM

Which one to choose between nodejs and java?

See all articles