本文将经过一个todo list先后端分离的小项目来说解如何用Node建立符合RESTful风格的API接口。css
咱们先来了解下如何用Node建立HTTP服务器(熟悉的读者能够直接跳过)。
用Node建立HTTP服务器是很是方便的,建立HTTP服务器要调用http.createServer()
函数,它只有一个参数,是个回调函数,服务器每次收到HTTP请求后都会调用这个回调函数。这个回调会收到两个参数,请求和响应对象,一般简写为req和res:html
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就是在程序逻辑运行前就把请求头和请求体都解析出来了。vue
Node不会自动往客户端写任何响应。在调用完请求回调函数以后,就要由你负责用res.end()方法结束响应了(见下图)。这样在结束响应以前,你能够在请求的生命期内运行任何你想运行的异步逻辑。若是你没能结束响应,请求会挂起,直到客户端超时,或者它会一直处于打开状态。ios
搭建HTTP服务器仅仅是个开始。接下来咱们来看看如何设定响应状态码
和响应头
中的字段,如何正确处理异常
。ajax
能够用res.setHeader(field, value)
来设置相应的响应头,下面是代码:json
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()以前。axios
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的内核之中。那些都要由第三方模块提供。后端
Roy Fielding博士在2000年提出了表征状态转移
(REST)。它是一种基于 HTTP 协议的网络应用的接口风格
。
依照规定,好比GET、POST、PUT和DELETE,分别与资源的获取、建立、更新和删除相对应。
HTTP 协议定义了如下8种标准的方法:跨域
建立标准的REST服务须要实现四个HTTP谓词。每一个谓词会覆盖一个操做:
接下来,咱们开始编写符合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谓词,若是你真的读懂了本文,那么相信这对你已经再也不是问题了。