前言

本文将通过一个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种标准的方法:

  1. GET:请求获取指定资源。
  2. HEAD:请求指定资源的响应头。
  3. POST:向指定资源提交数据。
  4. PUT:请求服务器存储一个资源。
  5. DELETE:请求服务器删除指定资源。
  6. TRACE:回显服务器收到的请求,主要用于测试或诊断。
  7. CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
  8. OPTIONS:返回服务器支持的HTTP请求方法。

创建标准的REST服务需要实现四个HTTP谓词。每个谓词会覆盖一个操作:

  1. GET:获取
  2. POST:新增
  3. PUT:更新
  4. 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接口的更多相关文章

  1. 利用 Django REST framework 编写 RESTful API

    利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...

  2. Node.js RESTful API

    什么是REST架构? REST表示代表性状态传输.REST是一种基于Web标准的架构,并使用HTTP协议. 它都是围绕着资源,其中每一个组件是资源和一个资源是由一个共同的接口使用HTTP的标准方法获得 ...

  3. Django编写RESTful API(一):序列化

    欢迎访问我的个人网站:www.comingnext.cn 关于RESTful API 现在,在开发的过程中,我们经常会听到前后端分离这个技术名词,顾名思义,就是前台的开发和后台的开发分离开.这个技术方 ...

  4. Spring Boot 2.x 编写 RESTful API (三) 程序层次 & 数据传输

    用Spring Boot编写RESTful API 学习笔记 程序的层次结构 相邻层级的数据传输 JavaBean 有一个 public 的无参构造方法 属性 private,且可以通过 get.se ...

  5. Spring Boot 2.x 编写 RESTful API (二) 校验

    用Spring Boot编写RESTful API 学习笔记 约束规则对子类依旧有效 groups 参数 每个约束用注解都有一个 groups 参数 可接收多个 class 类型 (必须是接口) 不声 ...

  6. 整合swagger2生成Restful Api接口文档

    整合swagger2生成Restful Api接口文档 swagger Restful文档生成工具 2017-9-30 官方地址:https://swagger.io/docs/specificati ...

  7. Spring Boot入门系列(二十一)如何优雅的设计 Restful API 接口版本号,实现 API 版本控制!

    前面介绍了Spring Boot 如何快速实现Restful api 接口,并以人员信息为例,设计了一套操作人员信息的接口.不清楚的可以看之前的文章:https://www.cnblogs.com/z ...

  8. 如何使用 Python 编写后端 API 接口

    如何使用 Python 编写后端 API 接口 get API Python3 # coding:utf-8 import json # ModuleNotFoundError: No module ...

  9. Postman如何通过xmysql工具的Restful API 接口访问MySQL

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 有时候用 Postman 接口测试需要获取MySQL的查询结果做接口输出的校验,这里介绍下 Postman 通过 R ...

随机推荐

  1. flutter图片组件

    在flutter中,image组件有很多构造函数,常用的包括Image.asset(本地图片)和Image.network(远程图片). 常用属性 不管是显示本地图片还是远程图片,image组件都包含 ...

  2. 在Windows系统使用Gpg4win进行加密解密

    GPG,又称为GnuPG,全称是Gnu Private Guard,即GNU隐私卫士.GPG是以PGP算法为核心的强大的加密软件.但GPG项目是一套命令行程序,而且是为 Linux 等开源操作系统设计 ...

  3. 简单数学算法demo和窗口跳转,关闭,弹框

     简单数学算法demo和窗口跳转,关闭,弹框demo <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...

  4. python中得字典和常用函数总结

    字典是python中一种常见得数据类型,用{}表示,并且以键值对得形式存放数据. dic={},其中得key键值是不可变得,类型可以是字符串.其中,列表,字典不可以作为键,键值是不可变得.字符串,元组 ...

  5. (转)maven怎么 引入(或引用/使用) 自定义(或本地/第三方) jar的三种方式 图文教程 方法二最简单

    转:https://blog.csdn.net/wabiaozia/article/details/52798194 准备工作: 假如我有一个自定义jar是:123456.jar,下载地址http:/ ...

  6. DTED文件结构

    注:DTED层级为1时,每列总计2414字节,包含1201个高度信息:DTED层级为2时,每列总计7214字节,包含3601个高度信息:DTED层级为3时,每列包含9001个高度信息. 每列数据前八个 ...

  7. nlp学习笔记

    https://mp.weixin.qq.com/s/-w4gENfBt2gKOPvghenw9w

  8. MySQL查询上一条记录和下一条记录

    如果ID是主键或者有索引,可以直接查找: 方法一: 查询上一条记录的SQL语句(如果有其他的查询条件记得加上other_conditions以免出现不必要的错误): select * from tab ...

  9. LeetCode刷题: 【120】三角形最小路径和

    1. 题目: 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] 自顶向下的最小 ...

  10. 迪杰斯特拉算法(Dijkstra)

    模板一: 时间复杂度O(n2) int dijkstra(int s,int m) //s为起点,m为终点 { memset(dist,,sizeof(dist)); //初始化,dist数组用来储存 ...