node.js - express #5

这几天一直看到 RESTful REST blahblah的资料,
但其实一直没有很明白RESTful是什么意思,因此决定透过实做来了解什么是RESTful了http://img2.58codes.com/2024/emoticon01.gif

首先,要来介绍什么是 REST

REST (Representational State Transfer) 中文翻译叫做「具象状态传输」,
是一种网路架构风格,目的是便于不同软体/程序在网络(例如网际网路)中互相传递信息。
-- Wikipedia

符合REST风格的Web API就被称为 RESTful API

以 API 而言,假设我们正在撰写一组待办事项的 API,

可能会有以下方式来作为 API 的 interface:

获取使用者资料 /getAllUsers
获取使用者1号资料 /getUser/1
新增使用者资料 /createUser
更新使用者资料 /updateUser/1
删除使用者资料 /deleteUser/1

若是以 REST 风格来开发 RESTful API 的话:

获取使用者资料 /GET /users
获取使用者1号资料 /GET /user/1
新增使用者资料 /POST /user
更新使用者资料 /PUT /user/1
删除使用者资料 /DELETE /user/1
--什么是 REST/RESTful

从这边就可以看出REST风格开发的充分利用了前面说过的HTTP method

而设计一个好的RESTful API有以下需要先了解

HTTP动词(只撷取常见的)

GET: 读取资源
PUT: 替换资源
DELETE: 删除资源
POST: 新增资源;也作为万用动词,处理其它要求

URI名词

URI由prefix + API endpoint组成,而Prefix的部份可有可无 (/api 可以省略)。

HTTP回传状态码

2xx: 成功
3xx: 重新导向
4xx: 用户端错误(用户端不应retry原始请求)
5xx: 伺服器错误(用户端可合理retry)

HTTP Header

HTTP Body: JSON或XML格式

RESTful API是一种设计风格,使API设计具有整体一致性,易于维护、扩展,且充份利用HTTP协定的特点。
-- 简明RESTful API设计要点

有个大略的了解后就开始来设计RESTful API吧!

第五个应用:製作RESTful Web API

参考来源: Build Node.js RESTful APIs in 10 Minutes

这次要来作一个简单的 ToDo List (底下的事项称作task)

建立一个待办事项(POST): /tasks读取一个待办事项(GET): /tasks/:taskId删除一个待办事项(DELETE): /tasks/:taskId读取整个待办事项列表(GET): /tasks更新一个待办事项(PUT): /tasks/:taskId

备注

因为Web API出错时通常传回的是HTTP状态码,因此如上面所说,必须要能看懂基本的意涵。如果想让他人也能存取API的话,可以参考跨来源资源共享 (CORS) 来管理

因为这次的练习牵涉到了后端,因此採用 Mongoose 来实作资料库。
Mongoos是一套给 Node.js 用的 MongoDB ODM 资料库

安装 MongoDB Windows / Linux / OS X 才能将结果存于资料库下载 Postman Chrome plugin 可以做HTTP动作的plugin,在之后可以帮忙做测试

上述都做好后就能开始做Todo List了!

打开你的终端机,在你想要建立todoListApi资料夹的地方输入 mkdir todoListApi

前往该资料夹 cd todoListApi
http://img2.58codes.com/2024/20105154CUhcGUUrQg.png
如上图,我自己是建立在桌面

输入npm init,之后会要求你输入名字、版本等讯息,
只有名字是必须输入的,其他均可以略过,我输入的名字是todolist
我们可以透过 npm init 来生成 package.json来定义相关套件,更多资讯可以点此处。

输入 touch server.js 在这个资料夹内建立 server.js

输入 mkdir api 建立一个api资料夹,并输入 mkdir api/controllers api/models api/routes api在底下建立三个不同的资料夹(models, routes, controllers)

输入 touch api/controllers/todoListController.js api/models/todoListModel.js api/routes/todoListRoutes.js 在三个资料夹底下分别建立对应的js档(还是空的)

所以现在你的资料夹看起来像是这样
http://img2.58codes.com/2024/20105154Nvj8dFGc8S.png

输入 npm install --save-dev nodemon 安装nodemon协助程式开发

输入 npm install express --save

输入 npm install mongoose --save 安装Mongoose

打开package.json在script的部分加上 "start": "nodemon server.js"
http://img2.58codes.com/2024/2010515468DKWTF598.png

补充: --save-dev 和 --save的用意

做完以上步骤后就能开始打code了!

设定伺服器(Server)

先打开 server.js 贴上以下的程式码

var express = require('express'),    app = express(),    port = process.env.PORT || 300;app.listen(port);console.log('todo list RESTful API server started on: ' + port);

在终端机输入 npm run start 就会发现server开始运作
http://img2.58codes.com/2024/20105154F3xyPVhxVW.png

设定资料表格式(Schema)

打开 todoListModel.js 贴上以下的程式码

'use strict'; //未必要写var mongoose = require('mongoose'); var Schema = mongoose.Schema;//建立一个model表现collection的样子(name, Created_date, status)并规定它的格式//collection包含name:任务名字 Created_date:建立日期 status:目前状态('pending', 'ongoing', 'completed')var TaskSchema = new Schema({  name: {    type: String,    Required: 'Kindly enter the name of the task'  },  Created_date: {    type: Date,    default: Date.now  },  status: {    type: [{      type: String,      enum: ['pending', 'ongoing', 'completed']    }],    default: ['pending']  }});module.exports = mongoose.model('Tasks', TaskSchema);

设定路由(Routes)

打开 todoListRoutes.js 贴上以下程式码

'use strict';module.exports = function(app) {    var todoList = require('../controllers/todoListController');    // todoList Routes    app.route('/tasks')        .get(todoList.list_all_tasks)        .post(todoList.create_a_task);    app.route('/tasks/:taskId')        .get(todoList.read_a_task)        .put(todoList.update_a_task)        .delete(todoList.delete_a_task);};

routing决定了server会如何回应HTML的请求(request)
这里有两种route(/tasks/tasks/:taskId)分别对应到不同的请求(GET/POSTGET/PUT/DELETE)以及回应

设定控制器(Controller)

打开 todoListController.js 贴上以下的程式码

'use strict';var mongoose = require('mongoose'),    Task = mongoose.model('Tasks');  //一开始建立的Tasks schema//针对不同request的回应(json格式)exports.list_all_tasks = function(req, res) {    Task.find({}, function(err, task) {        if (err)            res.send(err);        res.json(task);    });};//CRUDexports.create_a_task = function(req, res) {    var new_task = new Task(req.body);    new_task.save(function(err, task) {        if (err)            res.send(err);        res.json(task);    });};exports.read_a_task = function(req, res) {    Task.findById(req.params.taskId, function(err, task) {        if (err)            res.send(err);        res.json(task);    });};exports.update_a_task = function(req, res) {    Task.findOneAndUpdate(req.params.taskId, req.body, { new: true }, function(err, task) {        if (err)            res.send(err);        res.json(task);    });};exports.delete_a_task = function(req, res) {    Task.remove({        _id: req.params.taskId    }, function(err, task) {        if (err)            res.send(err);        res.json({ message: 'Task successfully deleted' });    });};

连接所有设定

修改 server.js 贴上以下的程式码

var express = require('express'),    app = express(),    port = process.env.PORT || 3000,    mongoose = require('mongoose'),    Task = require('./api/models/todoListModel'),    bodyParser = require('body-parser');mongoose.Promise = global.Promise;mongoose.connect('mongodb://localhost/Tododb');app.use(bodyParser.urlencoded({ extended: true }));app.use(bodyParser.json());var routes = require('./api/routes/todoListRoutes');routes(app);app.listen(port);console.log('todo list RESTful API server started on: ' + port);

透过URL连接MongoDB (Tododb)到server上

载入写好的Schema Tasks

安装、使用 bodyParser 解析回传的json资料

$ npm install --save body-parser

把之前写好的routes (todoListRoutes)挂上server的route上

启动mongoDB (可能要在mongoDB安装处才可使用此指令)

$ mongod

假使你的mongoDB需要重新启动,输入 rs 就能重新启动了

http://img2.58codes.com/2024/201051541CPINuM4GD.png
server成功画面如上图,可以开始测试功能了

使用Postman测试操作

开启你的Postman 输入 http://localhost:3000/tasks
得到的值应该要是 [] ,因为还没有任何task被建立

http://img2.58codes.com/2024/2010515466f40P8iWR.png

动作改为 POST,在key的部分写上name,value的部分写上task名称后送出就能新增task了
重複做多次后就如下图,使用GET得到的就不再是[]了

http://img2.58codes.com/2024/20105154qTNzyQ3DR1.png

要删除task的话,把动作改为 DELETE,网址改为 http://localhost:3000/tasks/taskid
就能够成功删除

http://img2.58codes.com/2024/20105154AcWLNh1oh1.png

GET,网址一样用 http://localhost:3000/tasks/taskid ,则是能得到单笔资料情形

http://img2.58codes.com/2024/20105154jwZS5vqT93.png

以上就是简单的restful api练习!

因为感冒 + 期中考 + 作业缠身,这篇文打了好久好久好久......


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章