详解Nodejs+Nest实现的短链接服务

本篇文章给大家介绍一下基于node框架nest实现短链接服务的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

详解Nodejs+Nest实现的短链接服务

推荐学习:《node》

日常生活中能见到各种奇怪的短链接,每次点击跳转的时候,笔者都会觉得神奇,这短链是怎么将用户引导到正确页面的呢?

短链原理

短链的原理就是以短博长,那么这个短的字符串怎么才能变成一长串链接呢?难道是靠某些神奇的加密算法?并不是,我们只需要依赖key/value的映射关系就能轻松实现这个看似神奇的以短博长

用一张图,大家就能清晰的看到我们访问短链的整个过程了。

未命名文件.png

首先,我们会有一个长链接,通过短链服务的处理,通常会输出一个只有一层目录的URL,然后我们可以将获取的URL进行分发。

然后就到了用户侧,用户点击短链之后,先到达的并不是目标页面,而是短链服务。

短链服务会截取链接上的pathname,并将其当做key,到映射关系中查找对应的value。

如果查到不到对应的value,则表示这个短链不存在或者已失效;如果查询成功,则会由短链服务直接302到value中的目标链接,完成一次短链访问。

具体实现

原料: node脚手架、Redis

整个实现分拆成3个部分:

① 接收长链接

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

登录后复制

在服务中创建一个createUrl接口,接收url已经type字段,并将其传入shorturlService中,等待短链接生成然后输出。

② 生成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 {    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;}

登录后复制

首先通过Math.random().toString(36).slice(-4)获取4位随机字符串,这个将会作为短链的pathname。

在进行映射之前,我们需要对其进行唯一性判断,虽然出现的可能性不大,但是还是需要防范短链覆盖这类的问题。本服务的解决方案是重试生成,如果短链值不幸重复时将会进入重试分支,服务将会内置可重试次数,如果重试的次数超过配置的字数,本次转换将会返回失败。

除了url,createUrl方法还接受一个type字段,这里涉及特殊短链的特性。我们短链有三种模式:

normal – 普通短链接,将会在规定时间内失效once – 一次性短链接,将会在规定时间内失效,被访问后自动失效permanent – 长期短链接,不会自动失效,只接受手动删除

生成urlKey之后,将会与type一起转成字符串储存到redis中,并输出拼接好的短链接。

③ 接收短链接并完成目标重定向

@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.getUrlasync 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;}

登录后复制

用户侧会获得一个类似http://localhost:8000/s/ku6a的链接,点击之后相当于是给短链接服务发送了一个GET请求。

服务接收到请求之后获取链接中key字段的值,也就是ku6a这个字符串,利用它查找Redis中的映射关系。

这里有两个分支,一个是在Redis中无法查询到相关的值,服务则认为短链接已经失效会直接return,因为getUrl返回了空值,重定向装饰器会将本次请求重定向到默认的目标链接中。

如果在Redis中顺利查到相关的值,则会读取其中的url和type字段,如果type为once则代表这个是一次性链接,会主动触发删除方法,最终都会返回目标链接。

额外功能

利用日志系统输出报表

使用短链接时,大概率都会需要相关的数据统计,怎么样在不使用数据库的前提下进行数据统计呢?

在本服务中,我们可以通过对落地日志文件的扫描,完成当日短链访问的报表。

在生成短链接的时候加上urlID字段进行统计区分并主动输出日志,如下:

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.306INFO[11999][-]createUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:38.323INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:39.399INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:40.281INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:40.997INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:41.977INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:42.870INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:43.716INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf2021-04-25 22:31:44.614INFO[11999][-]getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf

登录后复制

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

使用方式

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

node

具体启动方式

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

git clone https://github.com/mykurisu/shorturl.gitcd shorturlnpm installnpm 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.port8000服务启动端口redis.port6379redis端口redis.host0.0.0.0redis服务地址redis.db0redis具体储存库表cacheTyperedis短链储存模式,接受memory/redismaxRetryTimes5生成短链接最大重试次数defaultHosthttp://localhost:8000/s短链接前缀defaultIndexhttp://localhost:8000/defaultIndex短链接失效后重定向地址

内置接口

接口路由 请求方式 接口参数 接口用途

/s/createUrlPOSTurl: string, type?: string短链接生成接口/s/deleteUrlPOSTk: string删除短链接接口/s/:keyGETnone目标链接获取

拓展

① 储存降级策略

node是有本地储存方案的,也就是说我们是可以监听Redis的状态,如果断开连接时就临时将数据储存到内存中,以达到服务降级的目的。当然我们也可以直接使用内存来储存短链内容,在config.ts配置中可以进行更改。

② 不仅仅是短链接服务

让我们脱离短链接这个束缚,其实node本身已经是一个微型存储服务了,我们完全可以进行二次开发,输出更多的模块以支撑更多样的业务。

小结

整个短链接服务其实非常简单,麻烦的是服务的搭建,也就是迈出的第一步。笔者也是在无数次最初一步中挣扎,最终积累了node这么一个脚手架,希望能帮助到有同样境遇的同学。

另外,附上本文的服务源码 — node(欢迎大家Star)

更多编程相关知识,请访问:node!!

以上就是详解Nodejs+Nest实现的短链接服务的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2713589.html

(0)
上一篇 2025年3月7日 21:25:30
下一篇 2025年2月28日 02:59:25

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 聊聊Nodejs获取参数的四种方法

    本篇文章给大家介绍一下nodejs获取参数的四种方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 推荐学习:《nodejs》 获取请求很中的参数是每个web后台处理的必经之路,nodejs的 express框架 提供了…

    2025年3月7日
    200
  • 深入浅析Node.js中的进程和线程

    本篇文章带大家深入了解一下node.js中的进程和线程。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 进程与线程是一个程序员的必知概念,面试经常被问及,但是一些文章内容只是讲讲理论知识,可能一些小伙伴并没有真的理解,在实…

    2025年3月7日 编程技术
    200
  • 详解nodejs在控制台打印高亮代码的方法

    本篇文章给大家介绍一下nodejs如何在控制台打印高亮代码。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 当代码运行报错时,我们会打印错误,错误中有堆栈信息,可以定位到对应的代码位置。但有的时候我们希望能够更直接准确的打…

    2025年3月7日 编程技术
    200
  • 详解Nodejs Buffer模块的常用API

    本篇文章带大家详细介绍一下nodejs buffer模块的常用api。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 模块概览 Buffer是node的核心模块,开发者可以利用它来处理二进制数据,比如文件流的读写、网络请求…

    2025年3月7日
    200
  • Nodejs中使用string_decoder模块将buffer转成string

    本篇文章给大家介绍一下nodejs中使用string_decoder模块将buffer转成string的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 模块简介 string_decoder模块用于将Buffer转成…

    2025年3月7日
    200
  • nodejs设置NODE_ENV时发生错误怎么解决?

    本篇文章给大家介绍一下windows环境中nodejs设置node_env错误的解决方案。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 【推荐学习:《nodejs》】 今天在看node文档的时候,看到《Node.js 开…

    2025年3月7日 编程技术
    200
  • 详解Nodejs中的阻塞和非阻塞

    本篇文章带大家理解一下nodejs中的阻塞和非阻塞。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 推荐学习:《nodejs》 对于阻塞和非阻塞这两个概念大家应该都有一些自己的理解: 再简单说一下,阻塞大部分是由于同步模式…

    2025年3月7日
    200
  • 如何使用Nodejs连接Mysql,实现基本的增删改查操作

    本篇文章给大家介绍一下如何使用nodejs连接mysql,实现基本的增删改查(crud)操作。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 【推荐学习:《nodejs》】 接下来示例代码的主要技术点包括 基础框架 Koa…

    2025年3月7日 编程技术
    200
  • 深入了解调试nodejs程序的方法

    对于开发者来说,在开发应用程序的过程中,往往为了开发方便和解决bug需要借助于编程语言的调试功能。一般来说我们需要借助于强大IDE的调试功能来完成这项工作。nodejs也不例外。 今天我们来详细介绍一下如何调试nodejs程序。 开启nod…

    2025年3月7日 编程技术
    200
  • 浅谈浏览器中本地运行Node.js的方法

    本篇文章给大家介绍一下在浏览器中本地运行node.js的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。 【推荐学习:《nodejs 教程》】 一切要从收到一封邮件开始 大早上,我收到一封邮件,StackBlitz说正…

    2025年3月7日 编程技术
    200

发表回复

登录后才能评论