Restify快速上手

文章目录

  • Restify简介
    • 1. Restify是什么?
    • 2. 安装Restify
    • 3. 实现一个最简单的服务器
  • 处理程序链
    • 1. 什么是处理程序链
    • 2. next()函数
    • 3. 三类处理程序链
      • 3.1. 通用预处理程序链:pre
      • 3.2. 通用处理程序链:use
      • 3.3. 路由处理程序链
    • 4. 错误处理
  • 插件
    • 1. pre插件
      • 1.1. context
      • 1.2. dedupeSlashes
      • 1.3. sanitizePath
    • 2. use插件
      • 2.1. acceptParser
      • 2.2. queryParser
      • 2.3. bodyParser
      • 2.4. serveStatic
  • 鉴权机制
    • 1. 基本使用
    • 2. token过期和刷新

Restify简介

1. Restify是什么?

Restify是一个专注于RESTful API的nodejs框架。

2. 安装Restify

npm init -y
npm i restify -S

3. 实现一个最简单的服务器

var restify=require('restify')
var server=restify.createServer()server.get('/hello/:name',(req,res,next)=>{res.send('hello '+req.params.name)return next()
})server.listen(8000,()=>{console.log(server.name)console.log(server.url)
})
$ curl -is http://localhost:8000/hello/world
HTTP/1.1 200 OK
Server: restify
Content-Type: application/json
Content-Length: 13
Date: Sat, 20 Jan 2024 09:02:45 GMT
Connection: keep-alive
Keep-Alive: timeout=5"hello world"

处理程序链

1. 什么是处理程序链

所谓处理程序链,是指一组处理程序,按顺序依次执行。
如下,定义了针对’/hello/:name’路由的一组路由处理程序链:

server.get('/hello/:name',function(req,res,next){console.log('first step')return next() //程序链式执行的关键,不可省略},function(req,res,next){console.log('second step')res.send('how are you!') //在一条处理链上,只能向客户端返回一次数据。return next()},function(req,res,next){console.log('third step')return next()}
)

2. next()函数

处理程序链中的每个程序执行之后,都需要手工调用next(),这将移动到链中的下一个函数继续执行。调用res.send()不会自动触发next(),send()之后可能还要继续处理,因此也需要手动调用next()。

正常情况下,next()不需要任何参数。若由于某种原因(条件),需要提前终止程序链向后继续执行,可调用next(false)。

next()也接受Error类型对象,这将导致Restify向客户端发送错误状态码,错误状态码根据Error类型进行推断,Error类型为500,NotFoundError类型为404。关于错误处理,参见后文错误处理

server.get('/hello/:name',(req,res,next)=>{if(req.params.name=='') return next(new Error('no name!')res.send('hello '+req.params.name)return next()
})

3. 三类处理程序链

在Restify服务器中有三类处理程序链:

  • pre 在路由之前的处理程序链
  • use 在路由之后的处理程序链,对所有路由都生效
  • {httpVerb} 对特定路由执行的处理程序链,见上例

3.1. 通用预处理程序链:pre

pre对传入的所有请求都执行,即便请求的路由未注册。这可以用于记录日志或在路由之前清理传入的请求。

server.pre(function(req,res,next){console.warn('run before route! 1')return next()},function(req,res,next){console.warn('run before route! 2')return next()}
)

3.2. 通用处理程序链:use

use对所有被匹配的路由都执行。

server.use(function(req,res,next){console.warn('run for all routers! 1')return next()},function(req,res,next){console.warn('run for all routers! 2')return next()}
)

3.3. 路由处理程序链

Restify使用HTTP动词和参数来确定路由处理程序链。参数值可以通过req.params获取。

function send(req,res,next){res.send("hello "+req.params.name)return next()
}
server.post('/hello',function(req,res,next){res.send(201,Math.random().toString(36).substr(3,8))return next()
})
server.put('/hello',send)
server.get('/hello/:name',send)
server.del('/hello/:name',function(req,res,next){res.send(204)return next()
})

路由可以指定的HTTP动词包括:get、post、del、put、head、opts、patch。

4. 错误处理

Restify可以通过事件方式来处理错误。通过next(error)抛出错误事件,并用on()函数为特定错误事件添加侦听器。
restify-errors模块封装了一组常见HTTP和REST错误的构造函数。

const errs=require('restify-errors')server.get('/hello/:name',function(req,res,next){//找不到资源return next(new errs.NotFoundError())
})server.on('NotFound',function(req,res,err,callback){//不能调用res.send(),因为现在处于错误处理上下文,不在路由处理程序链中。//在此处可以记录错误日志或执行善后处理。//当完成错误处理后,调用回调函数回到路由处理程序链,Restify将根据错误类型自动发送包含错误代码的响应报文。return callback()
})

常用的错误事件如下:

  • 400 BadDigestError
  • 405 BadMethodError
  • 500 InternalError
  • 409 InvalidArgumentError
  • 400 InvalidContentError
  • 401 InvalidCredentialsError
  • 400 InvalidHeaderError
  • 400 InvalidVersionError
  • 409 MissingParameterError
  • 403 NotAuthorizedError
  • 412 PreconditionFailedError
  • 400 RequestExpiredError
  • 429 RequestThrottledError
  • 404 ResourceNotFoundError
  • 406 WrongAcceptError

插件

restify.plugins模块中提供过了一系列有用的插件,这些插件可以通过server.pre()或server.use()加载。

1. pre插件

pre类插件会在路由之前使用。

1.1. context

该插件给req添加了设置键值对req.set(key.val)和读取值req.get(key)方法。

server.pre(restify.plugins.pre.context())
server.get('/',function(req,res,next){req.set(myMessage,'hello world')return next()},function(req,res,next){res.send(req.get(myMessage))return next()}
)

1.2. dedupeSlashes

该插件会删除URL中重复斜杠,比如会将请求"/hello/abc"转换为"/hello/abc"。

server.pre(restify.plugins.pre.dedupeSlashes())
server.get('/hello/:name',function(req,res,next){res.send(200)return next()
})

1.3. sanitizePath

该插件修复URL,比如会将"/foo//bar//“转化为”/foo/bar"

server.pre(restify.plugins.pre.sanitizePath())
server.get('/hello/:name',function(req,res,next){res.send(200)return next()
})

2. use插件

use类插件会对所有路由生效。

2.1. acceptParser

解析Accept头,确保服务器可以提供客户要求的内容。若请求一个无法处理的类型,该插件会返回NotAcceptableError(406)错误。通过server.acceptable可获取restify服务器可接受的类型。

> server.acceptable
['application/json','text/plain','application/octet-stream','application/javascript'
]

通常,该插件都应该被加载:

server.use(restify.plugins.acceptParser(server.acceptable))

2.2. queryParser

解析HTTP查询字符串(如:/hello?name=abc&job=doctor)。若使用该插件,解析的内容在req.query中可用。
该插件接受一个选项参数mapParams,可配置是否将req.query合并到req.params字段中(req.params字段是针对/hello/:sex这类参数),若将mapParams配置为true,则类似/hello/male?name=abc&job=doctor这类路由,解析后的req.query为。

...
server.use(restify.plugins.queryParser({mapParams:true}))
server.get('/foo/:sex',(req,res,next)=>{res.send({'req.query':req.query,'req.params':req.params})return next()}
)
...
>curl -is -l "http://localhost:8000/foo/male?name=abc&title=def"
HTTP/1.1 200 OK
Server: restify
Content-Type: application/json
Content-Length: 72
Date: Sun, 21 Jan 2024 13:11:52 GMT
Connection: keep-alive
Keep-Alive: timeout=5{"req.query":{"name":"abc","title":"def"},"req.params":{"sex":"male","name":"abc","title":"def"}}

2.3. bodyParser

解析HTTP请求主体,解析后生成req.body字段。

...
server.use(restify.plugins.queryParser({mapParams:true}),restify.plugins.bodyParser()
)
server.get('/foo/:sex',(req,res,next)=>{res.send({'req.query':req.query,'req.params':req.params,'req.body':JSON.parse(req.body)})return next()}
)
...
>curl -is -X GET -d "{\"a\":1,\"b\":2,\"c\":{\"d\":3,\"e\":\"asdf\"}}" -l "http://localhost:8000/foo/male"
HTTP/1.1 200 OK
Server: restify
Content-Type: application/json
Content-Length: 92
Date: Sun, 21 Jan 2024 14:06:09 GMT
Connection: keep-alive
Keep-Alive: timeout=5{"req.query":{},"req.params":{"sex":"male"},"req.body":{"a":1,"b":2,"c":{"d":3,"e":"asdf"}}}

2.4. serveStatic

提供静态文件。该插件需要映射到路由上:

server.get('/static/*',restify.plugins.serveStatic({directory:__dirname,default:'index.html'
}))

实际路径为主程序所在目录(__dirname)+‘/static/’。

鉴权机制

Restify-auth是基于jwt的鉴权中间件。使用前需要先安装:

npm i restify-auth -S

1. 基本使用

const restify=require('restify')
const {restifyAuth} =require('restify-auth')const server=restify.createServer()
const auth=restifyAuth({secret:'test-secret'   //设定一个salt密码
})server.pre(restify.plugins.pre.sanitizePath())
server.use(restify.plugins.queryParser(),restify.plugins.bodyParser()
)
server.get('/getauth',auth.authorizer,    //在需要鉴权的路由添加async (req,res)=>{res.send(req.auth)}
)
server.post('/login',async (req,res)=>{var user=req.body.user||''var password=req.body.password||''if(user=="test"&&password=="test"){ //用户验证var token=await auth.sign({user})res.header('authorization',token)res.send({success:true})}else{res.send({success:false})}}
)server.on('restifyError',(req,res,err,cb)=>{console.log(err.toString())return cb()
})server.listen(8000,()=>{console.log(server.name)console.log(server.url)
})

客户端请求:

>curl -is -d "user=test&password=test" -l "http://localhost:8000/login"
HTTP/1.1 200 OK
Server: restify
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoidGVzdCIsImlhdCI6MTcwNTg0MDUzOCwiZXhwIjoxNzA1ODQxNzM4fQ.NK9F-FntUQHqXuEACQ94T2XKmTO3U8UxpZdaLegT8ko
Content-Type: application/json
Content-Length: 16
Date: Sun, 21 Jan 2024 12:35:38 GMT
Connection: keep-alive
Keep-Alive: timeout=5{"success":true}

在应答报文头中,authorization字段包含了从服务器返回的token,使用该token可访问服务器需要鉴权的路由:

>curl -is -H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoidGVzdCIsImlhdCI6MTcwNTg0MDUzOCwiZXhwIjoxNzA1ODQxNzM4fQ.NK9F-FntUQHqXuEACQ94T2XKmTO3U8UxpZdaLegT8ko" -l "http://localhost:8000/getauth"
HTTP/1.1 200 OK
Server: restify
Content-Type: application/json
Content-Length: 49
Date: Sun, 21 Jan 2024 12:38:20 GMT
Connection: keep-alive
Keep-Alive: timeout=5{"user":"test","iat":1705840538,"exp":1705841738}

若token错误,或不提供token,则无法访问该路由:

>curl -is -l "http://localhost:8000/getauth"
HTTP/1.1 401 Unauthorized
Server: restify
Content-Type: application/json
Content-Length: 53
Date: Sun, 21 Jan 2024 12:40:00 GMT
Connection: keep-alive
Keep-Alive: timeout=5{"code":"Unauthorized","message":"token is required"}

2. token过期和刷新

可设置token有效期和刷新周期:

...
const auth=restifyAuth({secret:'test-secret',expiresIn:'20m',    //有效期20分钟refreshRange:0.6    //刷新时间为超过有效期60%时,向客户端发送新token,新token在报文头的authorization字段中,客户端检测到新token后,应及时更新token。
})
...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/638687.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从一到无穷大 #21 从基于多数据模型分析负载的Benchmark讨论多模数据库的发展方向

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录 引言M2Bench测试结果从Lindorm看待多模的发展方向总结 引言 《M2Bench: A Database …

代码随想录算法训练营第五十三天| 1143.最长公共子序列、1035.不相交的线、53.最大子序和动态规划

代码随想录算法训练营第五十三天| 1143.最长公共子序列、1035.不相交的线、53.最大子序和动态规划 题目 1143.最长公共子序列 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符…

【手撕C语言 第六集】函数(上)

文章目录 一、函数是什么?二、C语言中函数的分类:1.库函数1.1 如何学会使用库函数? 2. 自定义函数 三、函数的参数1.实际参数(实参):2.形式参数(形参): 四、函数的调用&a…

P2717 寒假作业 CDQ

寒假作业 传送门 题目背景 zzs 和 zzy 正在被寒假作业折磨,然而他们有答案可以抄啊。 题目描述 他们共有 n n n 项寒假作业。zzy 给每项寒假作业都定义了一个疲劳值 a i a_i ai​,表示抄这个作业所要花的精力。 zzs 现在想要知道,有多…

Laravel 开发中总结的一些方式方法

1、最大限度地使用你的 .env 文件; 2、不要破坏框架核心,不要编辑 vendor 文件夹中的文件,你可以选择继承相关函数来实现。扩展优于修改 3、不要直接通过 PHPMyAdmin 或者其他数据库控制台创建表和索引。请使用数据库迁移表来创建表、增加修改字段&…

sqlserver2012 跨服务器查询

在 SQL Server 2012 中,跨服务器查询可以通过链接服务器来实现。以下是执行跨服务器查询的步骤: 创建链接服务器: 首先,你需要在 SQL Server 2012 上创建一个链接服务器对象。可以使用系统存储过程 sp_addlinkedserver 来完成这一…

spring refresh

preareRefresh:刷新前的工作准备 obtainFreshBeanFactory:获取子类刷新后的内部beanFactory实列 prepareBeanFactory:为容器注册必要的系统级别bean postProcessBeanFactory:允许容器的子类注册postProcessor invokeBeanFacto…

JS加密/解密之一个少见的js解密

直接上源代码 (function(){var tfK,EAc715-704;function JQI(d){var q514800;var yd.length;var i[];for(var v0;v<y;v){i[v]d.charAt(v)};for(var v0;v<y;v){var pq*(v245)(q%31355);var eq*(v264)(q%20133);var kp%y;var oe%y;var mi[k];i[k]i[o];i[o]m;q(pe)%3352359…

【漏洞复现】Hikvision综合安防管理平台config信息泄露漏洞

Nx01 产品简介 Hikvision&#xff08;海康威视&#xff09;是一家在中国颇具影响力的安防公司&#xff0c;其网络摄像头产品在市场上占据了相当大的份额。综合安防管理平台基于“统一软件技术架构”理念设计&#xff0c;采用业务组件化技术&#xff0c;满足平台在业务上的弹性扩…

本地cuda的部署方式

1首先在终端利用命令ndivia-smi查看自己的驱动版本和cuda version 查看是否匹配&#xff08;或者有没有安装cuda&#xff09; 查看是否匹配&#xff1a;知乎 - 安全中心 安装cuda&#xff1a;知乎 - 安全中心 2搞定cuda之后&#xff0c;就要安装与cuda相对应的pytorch版本。…

关于程序员的未来的这件事情,我是这么看的!

关于程序员的未来在哪里&#xff1f;很多想做程序员以及已经入坑的程序员都想知道&#xff0c;我作为一名工龄超过12年的资深大龄程序员&#xff0c;我其实也想知道&#xff0c;我也没办法确定程序员的未来在哪里。 或者我也不知道&#xff0c;为什么互联网当初招聘那么多的程…

【RL】(task2)策略梯度算法

note 文章目录 note一、策略梯度算法二、策略梯度算法的优缺点时间安排Reference 一、策略梯度算法 策略梯度&#xff08;Policy Gradient&#xff09;算法是一类用于解决强化学习问题的算法&#xff0c;它通过直接对策略进行参数化&#xff0c;并利用梯度上升的方法来优化策略…

【数据库原理】(37)Web与数据库

随着网络的高速发展和网络服务的日趋完善&#xff0c;网络上的信息量呈几何级数增长。为了有效地组织、存储、管理和使用网上的信息&#xff0c;数据库技术被广泛地应用于网络领域。特别是在Internet上&#xff0c;已建立了数以万计的网站&#xff0c;其中大中型网站的后台大多…

Leetcode 3017. Count the Number of Houses at a Certain Distance II

Leetcode 3017. Count the Number of Houses at a Certain Distance II 1. 解题思路2. 代码实现 题目链接&#xff1a;3017. Count the Number of Houses at a Certain Distance II 1. 解题思路 这一题其实思路上还是比较简单的&#xff0c;显然任何一个图都可以拆分为以下三…

【数据库原理】(38)数据仓库

数据仓库&#xff08;Data Warehouse, DW&#xff09;是为了满足企业决策分析需求而设计的数据环境&#xff0c;它与传统数据库有明显的不同。 一.数据库仓库概述 定义: 数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合&#xff0c;用于支持企业管理和…

机械设计-哈工大课程学习-螺旋传动

二、摩擦类型 1、静态摩擦&#xff1a;这是身体静止时所经历的摩擦。换句话说&#xff0c;就是身体有运动倾向时的摩擦力。 2、动态摩擦&#xff1a;这是身体在运动时所经历的摩擦。也称为动摩擦。动摩擦有以下两种类型&#xff1a; ①滑动摩擦&#xff1a;一个物体在另一个…

C# Socket通信从入门到精通(17)——单个异步UDP服务器监听一个客户端C#代码实现

前言: 我们在开发UDP通信程序时,除了开发UDP同步客户端程序,有时候我们也需要开发异步UDP服务器程序,所谓的异步最常见的应用就是服务器接收客户端数据以后,程序不会卡在数据接收这里,而是可以继续往下执行,这在实际项目中是经常会遇到的,所以说掌握异步UDP服务器程序…

学会这个工具,小白也可制作门窗电子画册

​随着互联网技术的发展&#xff0c;现在制作电子画册已经变得非常简单。如果你是一个新手&#xff0c;也可以通过学习一些技巧来制作门窗电子画册。 那么&#xff0c;如何制作门窗电子画册呢&#xff1f;其实&#xff0c;这个过程并不复杂。只需要一台电脑和一个基本的操作工具…

K8s(七)四层代理Service

Service概述 Service在Kubernetes中提供了一种抽象的方式来公开应用程序的网络访问&#xff0c;并提供了负载均衡和服务发现等功能&#xff0c;使得应用程序在集群内外都能够可靠地进行访问。 每个Service都会自动关联一个对应的Endpoint。当创建一个Service时&#xff0c;Ku…

Es bulk批量导入数据(1w+以上)

最近在学习es的理论知识以及实际操作&#xff0c;随时更新~ 概要&#xff1a;首先你得有1w条数据的json&#xff0c;然后用java读取json文件导入 一. 创建Json数据 首先我生成1.5w条数据&#xff0c;是为了实践分页查询&#xff0c;用from-size和scroll翻页去实践 生成四个字段…