「fastify项目实战」投票Web应用之六
「fastify项目实战」投票Web应用之五
「fastify项目实战」投票Web应用之四
「fastify项目实战」投票Web应用之三
「fastify项目实战」投票Web应用之二
「fastify项目实战」投票Web应用之一
在第三篇文章《投票Web应用之三》中,我们通过token功能实现了用户投票时的身份验证,在《投票Web应用之三》的图10中,通过检查客户端发送的请求是否包含一个名称为token的头域来决定是否需要继续处理当前的请求。如果请求中缺少此头域,那么就认为这是一个非法的请求,服务器会给出错误的响应。这样的逻辑判断对于其它的投票接口来说也是适用的,即我们希望访问每一个投票接口时,用户都能够提供对应的token值。但是在整个投票路由文件中,至少定义有7个路由方法需要添加对应的token验证功能,如果将token验证的代码全部复制到对应的路由方法中,其功能是可以达到目的。但是,这将引入了“潜在问题”的代码,fastify提供了一种很好的解决方案-钩子机制。
钩子是在fastify框架中注册的一些方法,它的注册对象可以是fastify实例、请求对象或响应对象,当这些对象在对应的生命周期事件发生时,这些钩子函数便会被触发。我们先看一个请求的生命周期图,这是fastify官方提供的事件顺序图。
图1
在图1中我们可以看到好多名称含有Hook的项,从上至下,表示消息请求到来时,每一个事件所对应的钩子函数调用顺序,第一个是onReqeust事件,第二个是preParsing事件以及后续的其它事件,直至最后的onResponse事件,当这些事件触发时,为这些事件所注册的钩子函数就会被执行。在图1中每一个事件的左侧表示当它的父插件抛出异常时它所提供的错误码。
当fastify实例处理来自客户端的请求时,请求对象中的事件会按照图1中的顺序自上而下触发,但是,如果其中某一个事件的钩子函数抛出了一个异常,那么,整个事件的处理链就会被中断,后续事件处理器和钩子方法全部不再会被调用。本文我们将利用钩子机制的这两个特性实现token在服务端的处理逻辑。
Token检查是指在调用路由处理器方法时,每一个请求必须携带一个token头域,如果没有这个token头域,那么,服务器将给出错误的响应,后续的处理器和钩子函数将不再被执行,我们称这样的机制为消息拦截机制。在之前的代码中,我们演示了路由处理器中判断token是否存在,但是,将这样的代码在每一个路由处理器方法中添加一遍不是一个好的方案。在图1中可以看到User Handler的调用时机位于onPreHandler事件之后,如果我们将判断是否含有token的时机放置在这个钩子函数中,通过钩子函数就实现了客户端每一次请求,就会自动地调用一次,如下图2所示。
图2
图2中第30行代码添加了preHandler事件的钩子函数,在钩子函数的第31行代码,获取请求对象request的头域中的token值,第32行代码判断所获取的token值是否存在,如果不存在,则抛出一个异常。反之,如果存在的话,程序正常执行。
图2
图2为客户端发送不含有token头域的消息时服务器给出的响应。通过使用钩子函数我们就实现了对所有投票请求中token头域的检查,而不需要在每一个路由处理器方法中分别添加对应的代码。
上一节我们通过preHandler钩子函数实现了对请求的拦截处理,如果满足特定条件,那么程序会执行正常的逻辑,否则,中断整个请求处理链。钩子函数除了这种用法之外,还有一种常用的方式:在钩子函数中向fastify对象中添加装饰器数据。因为在用户请求的处理器函数中很多情况下需要使用用户的Id信息,从token中获取用户Id值也是一个经常使用的功能,我们可以通过在钩子函数中将用户的Id值装饰到请求对象中,如下图3所示。
图3
图3中第31行代码使用getUserId方法获取token中的用户Id值,之后,将这个用户Id值赋值给请求对象的userId属性。getUserId方法是一个装饰器,它是通过下面的代码装饰到当前fastify对象中的。
图4
图4中定义了一个getUserId函数,它含有一个token参数,表示从客户端传来的token信息,第16行代码使用split将token的内容分为两部分,如果第一部分与第二部分的内容相对称,那么我们就认为是一个合法的用户Id值,将第一部分的内容作为用户Id值返回,这也是我们之前所采用的token加密方式。
完成上述的两个步骤之后,对于每一个来自客户端的请求,如果不含有token头域,那么,此请求就会会被服务器直接拒绝掉;反之,则从token信息中取出用户的Id值,并将其存放至请求对象中,之后所有处理链后续的其它请求都可以从请求对象中取出用户的Id值。例如用户的投票处理器函数是这样使用userId的,如下图5所示。
图5
图5中第81行代码使用的request.userId就是使用了在preHandler钩子函数中所设置的用户Id值。因为钩子方法会在每一个客户端请求发来时触发,因此,用户请求中的Id值对于每一个客户端请求都是有效的,包括获取投票列表、创建投票条目等,这样我们就实现了将用户Id值装饰到了请求对象中。
Fastify的钩子机制提供了一种拦截器的效果,通过使用钩子函数,我们既可以控制请求的处理链,也可以向处理链中添加各种数据。关于钩子的用法我们就先介绍到这里,谢谢各位阅读,我们下一篇文章见。
「fastify项目实战」投票Web应用之六
「fastify项目实战」投票Web应用之五
「fastify项目实战」投票Web应用之四
「fastify项目实战」投票Web应用之三
「fastify项目实战」投票Web应用之二
「fastify项目实战」投票Web应用之一
| 留言与评论(共有 0 条评论) “” |