用Node编写RESTful API接口
前言
本文将通过一个todo list前后端分离的小项目来讲解如何用Node创建符合RESTful风格的API接口。
创建HTTP服务器
我们先来了解下如何用Node创建HTTP服务器(熟悉的读者可以直接跳过)。
用Node创建HTTP服务器是非常方便的,创建HTTP服务器要调用http.createServer()
函数,它只有一个参数,是个回调函数,服务器每次收到HTTP请求后都会调用这个回调函数。这个回调会收到两个参数,请求和响应对象,通常简写为req和res:
var http = require('http')
var server = http.createServer(function(req, res){
res.end('Hello World')
})
server.listen(3000, '127.0.0.1')
运行上面的代码,在浏览器中访问http://localhost:3000
。然后你应该能看到一个包含“Hello World.”的普通文本页面。
服务器每收到一条HTTP请求,都会用新的req和res对象触发
回调函数。
在触发回调函数之前,Node会解析请求的HTTP头,并将它们作为req对象的一部分提供给请求回调。但Node不会在回调函数被触发之前开始对请求体的解析。这种做法跟某些服务端框架不同,比如PHP就是在程序逻辑运行前就把请求头和请求体都解析出来了。
Node不会自动往客户端写任何响应。在调用完请求回调函数之后,就要由你负责用res.end()方法结束响应了(见下图)。这样在结束响应之前,你可以在请求的生命期内运行任何你想运行的异步逻辑。如果你没能结束响应,请求会挂起,直到客户端超时,或者它会一直处于打开状态。
搭建HTTP服务器仅仅是个开始。接下来我们来看看如何设定响应状态码
和响应头
中的字段,如何正确处理异常
。
设置响应头
可以用res.setHeader(field, value)
来设置相应的响应头,下面是代码:
var http = require('http')
var server = http.createServer(function(req, res){
var body = '<h1>Hello Node</h1>'
res.setHeader('Content-Length', body.length)
res.setHeader('Content-Type', 'text/html')
res.end(body)
})
server.listen(3000)
设置状态码
我们经常需要返回默认状态码200之外的HTTP状态码。比较常见的情况是当所请求的资源不存在时返回一个404 Not Found状态码。
这可以通过设定res.statusCode属性
来实现。在程序响应期间可以随时给这个属性赋值,但必须在第一次调用res.write()或res.end()之前。
var http = require('http')
var server = http.createServer(function(req, res) {
var body = '<p>页面丢失了</p>'
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.statusCode = 404
res.end(body)
})
server.listen(3000, '127.0.0.1')
Node的策略是提供小而强的网络API,不同于Rails或Django之类的框架。像会话这种高级概念以及HTTP cookies这样的基础组件都没有包括在Node的内核之中。那些都要由第三方模块提供。
构建 RESTful Web 服务
Roy Fielding博士在2000年提出了表征状态转移
(REST)。它是一种基于 HTTP 协议的网络应用的接口风格
。
依照规定,比如GET、POST、PUT和DELETE,分别与资源的获取、创建、更新和删除相对应。
HTTP 协议定义了以下8种标准的方法:
- GET:请求获取指定资源。
- HEAD:请求指定资源的响应头。
- POST:向指定资源提交数据。
- PUT:请求服务器存储一个资源。
- DELETE:请求服务器删除指定资源。
- TRACE:回显服务器收到的请求,主要用于测试或诊断。
- CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
- OPTIONS:返回服务器支持的HTTP请求方法。
创建标准的REST服务需要实现四个HTTP谓词。每个谓词会覆盖一个操作:
- GET:获取
- POST:新增
- PUT:更新
- DELETE:删除
POST和GET请求
接下来,我们开始编写符合RESTful风格的GET和POST接口。
需求分析
项目决定采用前后端分离
,交互数据格式约定为json
,前端添加的数据提交到服务器后,由服务器存入服务器内存
中。前端界面如下:
首先,我们先编写前端部分。
前端部分
前端部分采用当今流行的vue.js作为框架,ajax请求采用axios库。代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1>Todo List</h1>
<ul>
<li v-for="(item, index) in items" :key="index">{{ item }}</li>
</ul>
<input type="text" v-model="item">
<button @click="postApi">button</button>
</div>
<script>
new Vue({
el: '#app',
data: {
items: [],
item: ''
},
created () {
axios.get('http://localhost:3000/')
.then(response => {
this.items = response.data
})
.catch(function (error) {
console.log(error)
})
},
methods: {
postApi () {
axios.post('http://localhost:3000/', {
item: this.item
})
.then(response => {
this.items = response.data
})
.catch(function (error) {
console.log(error)
})
}
}
})
</script>
</body>
</html>
后端部分
后端部分将用req.method
获取请求的HTTP谓词,并分情况对其进行处理。代码如下:
var http = require('http')
var items = []
http.createServer(function(req, res) {
// 设置cors跨域
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
res.setHeader('Content-Type', 'application/json')
switch (req.method) {
// 设置了cors跨域
// post请求时,浏览器会先发一次options请求,如果请求通过,则继续发送正式的post请求
case 'OPTIONS':
res.statusCode = 200
res.end()
break
case 'GET':
let data = JSON.stringify(items)
res.write(data)
res.end()
break
case 'POST':
let item = ''
req.on('data', function (chunk) {
item += chunk
})
req.on('end', function () {
// 存入
item = JSON.parse(item)
items.push(item.item)
// 返回到客户端
let data = JSON.stringify(items)
res.write(data)
res.end()
})
break
}
}).listen(3000)
console.log('http server is start...')
小结
当然,一个完整的RESTful服务还应该实现PUT谓词和DELETE谓词,如果你真的读懂了本文,那么相信这对你已经不再是问题了。
用Node编写RESTful API接口的更多相关文章
- 利用 Django REST framework 编写 RESTful API
利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...
- Node.js RESTful API
什么是REST架构? REST表示代表性状态传输.REST是一种基于Web标准的架构,并使用HTTP协议. 它都是围绕着资源,其中每一个组件是资源和一个资源是由一个共同的接口使用HTTP的标准方法获得 ...
- Django编写RESTful API(一):序列化
欢迎访问我的个人网站:www.comingnext.cn 关于RESTful API 现在,在开发的过程中,我们经常会听到前后端分离这个技术名词,顾名思义,就是前台的开发和后台的开发分离开.这个技术方 ...
- Spring Boot 2.x 编写 RESTful API (三) 程序层次 & 数据传输
用Spring Boot编写RESTful API 学习笔记 程序的层次结构 相邻层级的数据传输 JavaBean 有一个 public 的无参构造方法 属性 private,且可以通过 get.se ...
- Spring Boot 2.x 编写 RESTful API (二) 校验
用Spring Boot编写RESTful API 学习笔记 约束规则对子类依旧有效 groups 参数 每个约束用注解都有一个 groups 参数 可接收多个 class 类型 (必须是接口) 不声 ...
- 整合swagger2生成Restful Api接口文档
整合swagger2生成Restful Api接口文档 swagger Restful文档生成工具 2017-9-30 官方地址:https://swagger.io/docs/specificati ...
- Spring Boot入门系列(二十一)如何优雅的设计 Restful API 接口版本号,实现 API 版本控制!
前面介绍了Spring Boot 如何快速实现Restful api 接口,并以人员信息为例,设计了一套操作人员信息的接口.不清楚的可以看之前的文章:https://www.cnblogs.com/z ...
- 如何使用 Python 编写后端 API 接口
如何使用 Python 编写后端 API 接口 get API Python3 # coding:utf-8 import json # ModuleNotFoundError: No module ...
- Postman如何通过xmysql工具的Restful API 接口访问MySQL
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 有时候用 Postman 接口测试需要获取MySQL的查询结果做接口输出的校验,这里介绍下 Postman 通过 R ...
随机推荐
- CF 717A Festival Organization——斯特林数+递推求通项+扩域
题目:http://codeforces.com/contest/717/problem/A 是 BJOI2019 勘破神机 的弱化版. 令 \( g[i] \) 表示长为 i .以 1 结尾的方案数 ...
- scrapy工作流程
整个scrapy流程,我们可以用去超市取货的过程来比喻一下 两个采购员小王和小李开着采购车,来到一个大型商场采购公司月饼.到了商场之后,小李(spider)来到商场前台,找到服务台小花(引擎)并对她说 ...
- 浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)(转)
引子 STM32的硬件I2C很多人都对它望而却步.因为很多电工都说,STM32 硬件 I2C有BUG.不稳定.死机等等……最后都使用GPIO模拟I2C. 的确,模拟I2C好用.但是在我看来在一个72M ...
- websocket 和 http的区别
相同点: 都是基于tcp实现的,都要经过三次握手.四次挥手. 如图: 不同点: websocket 经历过连接,就可以全双工通信,不需要一直连接,降低了网络资源消耗. http 每次通讯都要连接,客户 ...
- 如何为mysql建立索引
前些时候,一位颇高级的程序员居然问我什么叫做索引,令我感到十分的惊奇,我想这绝不会是沧海一粟,因为有成千上万的开发者(可能大部分是使用MySQL的)都没有受过有关数据库的正规培训,尽管他们都为客户做过 ...
- Java并发:搞定线程池(上)
原文地址:https://www.nowcoder.com/discuss/152050?type=0&order=0&pos=6&page=0 本文是在原文的基础+理解,想要 ...
- VM虚拟机启动centos出现内部错误
内部错误 解决办法 1.关闭虚拟机后,单击VM,右键,以管理员身份运行. 2.找到电脑的 管理— Vmware workstation server ,默认状态下是手动,把他改为自动重启就可以啦.
- hdu3438 Buy and Resell(优先队列+贪心)
Buy and Resell Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- WPF-将DataGrid控件中的数据导出到Excel
原文:WPF-将DataGrid控件中的数据导出到Excel 导出至Excel是非常常见,我们可以用很多类库,例如Aspose.NOPI.Interop,在这里我们使用微软自家的工具.我的WPF绑定的 ...
- Codeforces Fix a Tree
Fix a Tree time limit per test2 seconds A tree is an undirected connected graph without cycles. Let' ...