用Node编写RESTful API接口的示例代码


Posted in Javascript onJuly 04, 2018

前言

本文介绍了如何用Node开发web程序,并通过一个todo list练习来介绍如何创建符合RESTful风格的API接口。

创建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()方法结束响应了(见下图)。这样在结束响应之前,你可以在请求的生命期内运行任何你想运行的异步逻辑。如果你没能结束响应,请求会挂起,直到客户端超时,或者它会一直处于打开状态。

用Node编写RESTful API接口的示例代码

搭建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请求

接下来,通过一个todo list练习来编写RESTful风格的GET和POST接口。

需求分析

项目采用前后端分离,交互数据格式约定为json,前端添加的数据提交到服务器后,由服务器存入服务器内存中。前端界面如下:

用Node编写RESTful API接口的示例代码

首先,我们先编写前端部分。

前端部分

前端采用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>

后端部分

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...')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
浅析jQuery中常用的元素查找方法总结
Jul 04 Javascript
使用JS或jQuery模拟鼠标点击a标签事件代码
Mar 10 Javascript
javascript实现单击和双击并存的方法
Dec 13 Javascript
微信公众号-获取用户信息(网页授权获取)实现步骤
Oct 21 Javascript
Bootstrap的class样式小结
Dec 01 Javascript
微信小程序 免费SSL证书https、TLS版本问题的解决办法
Dec 14 Javascript
微信小程序之绑定点击事件实例详解
Jul 07 Javascript
Angular4学习笔记之实现绑定和分包
Aug 01 Javascript
基于vue-router 多级路由redirect 重定向的问题
Sep 03 Javascript
默认浏览器设置及vue自动打开页面的方法
Sep 21 Javascript
详解Vue项目部署遇到的问题及解决方案
Jan 11 Javascript
微信小程序封装的HTTP请求示例【附升级版】
May 11 Javascript
微信小程序踩坑记录之解决tabBar.list[3].selectedIconPath大小超过40kb
Jul 04 #Javascript
JS实现点击按钮可实现编辑功能
Jul 03 #Javascript
详解vue-cli中模拟数据的两种方法
Jul 03 #Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
Jul 03 #Javascript
基于React+Redux的SSR实现方法
Jul 03 #Javascript
VUE 3D轮播图封装实现方法
Jul 03 #Javascript
vue.js轮播图组件使用方法详解
Jul 03 #Javascript
You might like
比较discuz和ecshop的截取字符串函数php版
2012/09/03 PHP
在windows服务器开启php的gd库phpinfo中未发现
2013/01/13 PHP
php创建、获取cookie及基础要点分析
2015/01/26 PHP
Yii实现文章列表置顶功能示例
2016/10/18 PHP
非常不错的一个javascript 类
2006/11/07 Javascript
JavaScript自执行闭包的小例子
2013/06/29 Javascript
js中浮点型运算BUG的解决方法说明
2014/01/06 Javascript
JavaScript获取两个数组交集的方法
2015/06/09 Javascript
基于gulp合并压缩Seajs模块的方式说明
2016/06/14 Javascript
JavaScript中获取时间的函数集
2016/08/16 Javascript
微信小程序本作用域下调用全局JS详解及实例
2017/02/22 Javascript
Vue异步组件使用详解
2017/04/08 Javascript
jQuery+ajax实现局部刷新的两种方法
2017/06/08 jQuery
总结js函数相关知识点
2018/02/27 Javascript
详解Vue 全局变量,局部变量
2019/04/17 Javascript
[01:12:53]完美世界DOTA2联赛PWL S2 Forest vs SZ 第一场 11.25
2020/11/26 DOTA
Python实现比较两个文件夹中代码变化的方法
2015/07/10 Python
Django与遗留的数据库整合的方法指南
2015/07/24 Python
python删除本地夹里重复文件的方法
2020/11/19 Python
对pandas中Series的map函数详解
2018/07/25 Python
Python如何处理大数据?3个技巧效率提升攻略(推荐)
2019/04/15 Python
详解Numpy中的数组拼接、合并操作(concatenate, append, stack, hstack, vstack, r_, c_等)
2019/05/27 Python
Python matplotlib学习笔记之坐标轴范围
2019/06/28 Python
Django REST framework内置路由用法
2019/07/26 Python
python groupby 函数 as_index详解
2019/12/16 Python
python matplotlib:plt.scatter() 大小和颜色参数详解
2020/04/14 Python
Django基于Models定制Admin后台实现过程解析
2020/11/11 Python
pycharm 如何取消连按两下shift出现的全局搜索
2021/01/15 Python
PyCharm+Miniconda3安装配置教程详解
2021/02/16 Python
2014三八妇女节活动总结范文四篇
2014/03/09 职场文书
还款承诺书范文
2014/05/20 职场文书
运动会的口号
2014/06/09 职场文书
食堂标语大全
2014/06/11 职场文书
房屋租赁授权委托书范本
2014/09/20 职场文书
离婚财产分配协议书
2014/10/21 职场文书
幼儿学前班评语
2014/12/29 职场文书