Nodejs随学随记(杂)
1、环境定制配置文件及NODE_ENV设置
环境变量是程序运行环境的一些参数,用于配置不同运行环境下的功能配置。
环境定制指的是依据NODE_ENV配置,开发和测试环境拉取不同的配置文件。这些环境变量出现在程序的process.env对象中。
在Unix中设置环境变量:$ NODE_ENV= xxx node app
在Windows中设置环境变量:$ set NODE_ENV=production & node app
推荐模块:config-lite,使用参考:不同环境下配置使用(https://segmentfault.com/a/1190000010099383)
其中,在windows中配置NODE_ENV的设置不生效的问题,
推荐模块:cross-env,使用参考: 使用cross-env解决跨平台设置NODE_ENV的问题(https://segmentfault.com/a/1190000005811347)
2、创建http服务器一组request对象
"req": { "url": "/performance-now.js.map", "headers": { "host": "localhost:3000", "connection": "keep-alive", "cache-control": "no-cache", "user-agent": "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36", "accept-encoding": "gzip, deflate, br", "accept-language": "zh-CN,zh;q=0.9,ar;q=0.8,cs;q=0.7,de;q=0.6,en;q=0.5,es;q=0.4,fr;q=0.3,gl;q=0.2,hu;q=0.1,id;q=0.1,it;q=0.1,ja;q=0.1,ko;q=0.1,ms;q=0.1,pl;q=0.1,pt;q=0.1,ru;q=0.1,th;q=0.1,tr;q=0.1,vi;q=0.1,zh-TW;q=0.1", "cookie": "myblog=s%3AVE5neyqvgvIhgSOiU_MRNypeYqJvd7bs.qpxxKHewlaZJ68cN0mzNQtH6sGSnE2GraxTrBatpARU; blog-demo=s%3AwHNEMnXL9oTMwgqEM2g2QdrMM23oZA4P.puTN0wUBP3CWRgoeZzaDBFoPRtqnLEnTcFQfvVr%2FU7c; io=wtQDO9oCtfs0qObOAAAB" }, "method": "GET", "httpVersion": "1.1", "originalUrl": "/performance-now.js.map", "query": {} },
3、日志记录
最常用的日志记录包括:访问日志、错误日志。
推荐模块:Winston & express-winston、log4js 使用推荐:log4js日志管理(https://www.cnblogs.com/yjfengwen/p/3827217.html)
// 正常请求的日志 app.use(expressWinston.logger({ transports: [ new (winston.transports.Console)({ json: true, colorize: true }), new winston.transports.File({ filename: 'logs/success.log' }) ] })) // 错误请求的日志 app.use(expressWinston.errorLogger({ transports: [ new winston.transports.Console({ json: true, colorize: true }), new winston.transports.File({ filename: 'logs/error.log' }) ] }))
4、包配置文件
模块:package,用于获取项目package.json配置文件的任意配置
5、页面消息管理
模块:connect-flash,因为flash是session中存储信息的特殊区域,此类信息展示给用户之后就被删除。
所以,需要和express-session中间件配合使用。
如何使用?
首先,使用 cookieParser 和 session 中间件来设置session:
const flash = require('connect-flash'); const express = require('express'); const session = require('express-session'); var app = express(); app.configure(function() { app.use(express.cookieParser('keyboard cat')); app.use(express.session({ cookie: { maxAge: 60000 }})); app.use(flash()); });
待使用了flash中间件后,所有的requests请求调用flash()函数来处理flash信息。
app.get('/flash', function(req, res){ // 通过调用req.flash(),设置flash 提示信息 req.flash('info', 'Flash is back!') res.redirect('/'); }); app.get('/', function(req, res){ // 通过key设置flash信息 res.render('index', { messages: req.flash('info') }); });
6、Session管理
Session是一块存储在服务器端的内存空间,用于存储客户端在一个回话期间的操作记录。验证会话身份的SessionId标示参数。客户端、服务器设置、获取、传输SessionId过程如下:
- 客户端向服务器发起请求,服务器先检查响应头是否带有记录了SessionId的Cookie;
- 如果没找到SessionId,表示是首次访问。服务器会开辟Session空间并生成一个新的SessionId,并通过headers响应头的Set-Cookie:SessionId=xxxxxxx,向客户端发送要求设置cookie的响应;
- 客户端收到响应后,在本地设置SessionId的cookie信息,其中,这段cookie的有效时间至浏览器会话结束;
- 之后,同一客户端每次向同一网站(服务器)发送请求,请求头都会带上此SessionId的cookie信息;
- 服务器接收到响应,读取headers请求头中的cookie信息,得到SessionId。
见下图:
注意:
- 请求头中的信息,只有浏览器第一次访问服务器,服务器才会在响应头添加 Set-Cookie,其他时候,响应头传递的都是Cookie信息。
- Session 也可以设置超时时间,也就是说,即便cookie信息还生效,回话没结束,只要Session信息超时过期了,SessionId也就失效了。
以上,仅仅考虑到单个用户、单台服务器的情况,若干涉及到web集群化、多服务器节点、Session信息持久化等情况就会复杂的多。
7、locals变量
express的 locals变量用来设置变量值,常用作模板的model数据。
locals可以定义于app(app.locals)对象,也可能定义于res(res.locals)对象。
其中,app.locals会在app整个生命程序中起作用,而res.locals只能对回调的请求中起作用。由于app.locals能在整个生命周期访问,所以常常将该对象定义一些顶级、全局的数据。
8、创建HTTPS服务
https是安全版的http服务,即在传统的超文本传输协议基础上增加了SSL加密层,SSL依靠证书验证服务器的省份,并为浏览器和服务器之间的通信加密。与HTTP相比,HTTPS更加安全,但需要到ca申请证书。
// 生成私钥key文件命令 > openssl genrsa 1024 > ./sslcert/private.pem // 通过私钥文件生成CSR证书签名 > openssl req -new -key ./sslcert/private.pem -out csr.pem // 通过私钥文件和CSR证书签名生成证书文件 > openssl x509 -req -days 365 -in csr.pem -signkey ./sslcert/private.pem -out ./sslcert/file.crt // 基本的创建代码 var app = require("express")() var fs = require("fs") var http = require("http") var https = require("https") var priv = fs.readFileSync('./sslcert/private.pem', 'utf8') var cert = fs.readFileSync('./sslcert/file.crt', 'utf8') var credentials = { key: priv, cert: cert } var httpServer = http.createServer(app) var httpsServer = https.createServer(credentials, app) httpServer.listen(8080) httpsServer.listen(8443) app.get("/", (req, res) => { if(req.protocol == 'https'){ res.status(200).send("welcome to safety land!") }else{ res.status(200).send("welcome!") } })
9、套接字及其作用
网络编程的两个主要问题:一、如何快速准确的定位查找一台或多台主机;二、如何高效安全的传输数据。为了区分不同应用程序进程和连接,许多操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口。
套接字通常由三个参数组成:IP地址、使用的传输协议(TCP or UDP)及使用的端口号。
Socket可以看作在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另一个Socket,使这段信息传送到其他程序中。
要进行互联网通信,至少需要一对套接字:一个运行于客户端,称之为ClientSocket;一个运行于服务器端,称之为ServerClient。
套接字的连接分为三个步骤:客户端请求、服务端监听、连接确认。
服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。