node构建自己的API服务器系列一:日志服务

原创 Dean 程序相关,系列文章 二维码阅读
2018-10-01 08:34

说实在的,我是一个特别不擅长写作的人,你要让我写一篇总结或者技术文章,我就恨不能直接将代码贴在文章里别的什么都不写,直接让别人去看,但是这样是不行的。我看的东西很多,也有积累一些干货,想分享给更多的朋友,但是害怕自己写不好,说的不清楚,误导了别人,但是凡事总的慢慢尝试,挑战,学习,积累,才会不断提升,从今天开始我准备尝试写一系列专题主题,主题想的挺多的,只能说一个一个来吧,如果写的不好或者有问题的地方请大家及时指正。

这个专题我准备分享的是如何使用nodejs构建一个属于自己的API服务器,由易到难,从无到有,这篇文章主要涉及到的内容是搭建API服务器的基础架构,实现一个简单但却很实用的通用日志服务。

一、准备工作

开始之前请确保你的电脑上已经安装好了最新的nodejs环境并正常运行,为什么要最新,因为我们后面会用到一些es6的写法,如果还没有安装,可以参考https://www.runoob.com/nodejs/nodejs-install-setup.html中的描述安装。

二、框架选择

在这里我们直接选用express框架,虽然据说express的作者已经抛弃他并极力推荐他的新框架koa,但是我还是觉得express比较好用,相比exprees来说,koa就相当于是一个纯架子,你要使用的任何东西(中间件)都需要自己手动安装,而express默认为我们附带了一些基础的中间件,虽然其体积在一定程度上会有所增加,但是还是方便了很多。接下来我们就准备开始搭建基础架构了。

三、搭建基础结构

首先我们创建一个目录API用于存放我们的项目,打开命令行工具使用npm命令

npm init -y

来生成我们项目的package.json文件(不知道这个是干嘛的请自行科普),生成好的文件内容如下:

{
  "name": "API",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

这些参数是什么意思,这里就不多做阐述了,不知道的请自行查资料了解。

在生成了package.json文件后,我们需要确定我们项目的结构了。首先我们需要一个入口文件index.js用于实例化express并创建监听端口,我们还需要一个routes目录,我们以后会将所有的路由文件都放在这里。我们还需要一个config目录,用于存放一些配置文件,一个sources目录用于存放一些资源文件,一个utils目录用于存放一些工具方法,到目前为止,我们的目录结构:

- API
- index.js
- routes
- config
- sources
- utils

现在下面的文件夹还都是空的,之后我们会一个个创建文件填充。

讲到这里可能有人会问,为什么不用express-generater, 这个缺失很方便,很强大,就是因为功能太全,在学习的时候可能会干扰我们的视线。

现在基本目录结构我们已经确定了,可以着手开始开发我们的API服务器了。

四、开始开发并构建日志服务

如果你对express还没有了解,你可以点击这里移步官网先熟悉一下API。

上面我们确定了实用express作为框架,那么我们现在需要安装express依赖,在命令行工具中通过命令:

npm i express --save-dev

等安装完成后,我们就要着手编写我们的入口文件index.js了,开始之前先想想入口文件需要做什么事情呢?

1、实例化express

2、创建监听端口

3、创建路由规则,当请求到来根据路由规则分发到对应的路由处理器处理完成后响应客户端,代码如下:

const express = require('express');     

// 监听端口号
const listenePort = 1314;

// 实例化express
const app = express();

// 创建监听端口
app.listen(listenePort);

console.log(`server listening at port ${listenePort}`);

我们现在在命令行运行

node iddex.js

就可以启动服务了,当然现在我们现在还没有加入任何路由规则,下面我们就开始编写日志服务了。同样的在开始之前我们先构思一下日志服务需要做些什么工作?

1、写入特定类型的日志

2、读取日志,包括全部日志和特定类型的日志

根据功能我们确定路由规则,首先我们确定基路由为log

1、/log 获取所有的日志

2、/log/:type 获取特定类型的日志

3、/log/hello/:type 写入特定类型的日志

路由规则确定后,我们就开始编写具体的代码了,此处为了方便直接使用json来存储了,实际开发中你最好选择mongodb或者mysql等数据库来存储数据。

1、在sources目录下创建log.json,初始内容为[]

2、在routes目录下创建log.js文件左右log服务处理器并编写具体逻辑,代码如下:

const fs = require('fs');
const path = require('path');
const express = require('express');

const sourcePath = path.join(__dirname, '../sources/log.json');

// 导入工具方法
const { setHeader, setJSONResponse } = require('../utils/res');
const getIp = require('../utils/getIp');

const router = express.Router();

// 获取所有日志
router.get('/', (req, res) => {
	setHeader(res, 'Access-Control-Allow-Origin', '*');
	fs.readFile(sourcePath, (err, data) => {
		if (err) {
			setJSONResponse(res, { ret: -1 });
		} else {
			const logs = JSON.parse(data.toString());
			setJSONResponse(res, { ret: 0, data: logs });
		}
	});
});

// 获取特特定类型的所有日志
router.get('/:type', (req, res) => {
	setHeader(res, 'Access-Control-Allow-Origin', '*');
	fs.readFile(sourcePath, (err, data) => {
		if (err) {
			setJSONResponse(res, { ret: -1 });
		} else {
			const { type } = req.params;
			let logs = JSON.parse(data.toString());
			if (type) {
				logs = logs.filter(log => {
					return log.type === type;
				});
			}
			setJSONResponse(res, { ret: 0, data: logs });
		}
	});
});

// 写入特定类型的日志
router.get('/hello/:type', (req, res) => {
	setHeader(res, 'Access-Control-Allow-Origin', '*');
	fs.readFile(sourcePath, (err, data) => {
		if (err) {
			setJSONResponse(res, { ret: -1 });
		} else {
			const logs = JSON.parse(data.toString());

			const { headers, params } = req;
			const { type } = params;

			const logItem = {
				ip: getIp(req),
				time: Date.now(),
				userAgent: headers['user-agent'],
				language: headers['accept-language'],
				type
			};

			logs.push(logItem);

			fs.writeFile(sourcePath, JSON.stringify(logs), (err) =>  {
				if (err) {
					setJSONResponse(res, { ret: -1 });
				} else {
					setJSONResponse(res, { ret: 0 });
				}
			});
		}
	});
});

module.exports = router;

注意这个里面导入了两个工具方法:
1)res.js, 服务端响应辅助

function setHeader(res, key, value) {
	res.setHeader(key, value);
}

function setJSONResponse(res, response) {
	res.end(JSON.stringify(response));
}

module.exports = {
	setHeader,
	setJSONResponse
};

2)getIp.js,获取客户端IP地址

function getIP(req){
  var ipAddress;
  var headers = req.headers;
  var forwardedIpsStr = headers['x-real-ip'] || headers['x-forwarded-for'];
  ipAddress = forwardedIpsStr ? forwardedIpsStr : null;
  if (!ipAddress) {
    ipAddress = req.connection.remoteAddress;
  }
  return ipAddress;
}

module.exports = getIP;

请自行将以上两个文件放到对应的目录

3、目前我们已经建立好了路由处理器,现在需要在入口文件中导入处理器然后建立路由映射关系了,代码如下:

const express = require('express');  
 
//导入路由处理器
const logHandler = require('./routes/log');   

// 监听端口号
const listenePort = 1314;

// 实例化express
const app = express();

// 建立路由映射关系
app.use('/log', logHandler);

// 创建监听端口
app.listen(listenePort);

console.log(`server listening at port ${listenePort}`);

到此为止,我们已经建立了一个完整的日志服务,现在我们可以通过

node index.js

启动API服务器,访问http://127.0.0.1:1314/log/hello/blog,然后我们查看sources目录下的log.json文件,发现里面添加了一条记录,我们可以再多添加几条记录,不同类型的都添加几条,然后通过访问http://127.0.0.1:1314/log获取所有日志,通过访问http://127.0.0.1:1314/log/blog获取blog相关的记录。

到这里,我们的第一节就结束了,主要讲了基础架构的搭建以及日志服务的编写,其实还是挺简单的,在线案例就不提供了,可以按照上面的步骤本地搭建一个,你可以点击这里下载示例代码。

系列文章导航:

第二节:node构建自己的API服务器系列二:IP解析服务

第三节:node构建自己的API服务器系列三:代理服务

第四节:node构建自己的API服务器系列四:快递单识别服务

第五节:node构建自己的API服务器系列五:邮件发送服务

本文地址:https://www.deanhan.cn/node-api-server-series-1.html
版权声明:本文为原创文章,版权归 Dean 所有,欢迎分享本文,转载请保留出处!
  • 支付宝二维码 支付宝
  • 微信二维码 微信