一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情。
http 模块
http 模块建立在 net 模块之上, 无需手动管理 socket 也无需手动组装消息格式。
利用 htpp 模块实现网络请求:
// 实现 GET 请求
const http = require('http');
// request 是一个流
const request = http.request("http://juejin.cn/", {
method: "GET",
}, resp => {
console.log("服务器响应的状态码", resp.statusCode);
console.log("服务器响应头", resp.headers);
// 响应体需要用流来读取
let res = '';
resp.on("data", chunk => {
res += chunk.toString('utf-8')
})
resp.on('end', chunk => {
console.log(res);
})
})
request.end(); // 表示消息体结束
利用 http 模块实现服务器:
const http = require('http');
const url = require("url");
function handleReq(req){
console.log('监听到网络请求');
const urlObj = url.parse(req.url);
console.log("请求地址", urlObj);
console.log("请求方法", req.method);
console.log('请求头', req.headers);
let body = "";
req.on('data', chunk => {
body += chunk.toString('utf-8');
})
req.on('end', () => {
console.log("请求体", body);
})
}
const server = http.createServer((req, res) => {
handleReq(req);
res.setHeader("a", 1);
res.setHeader("b", 2);
res.statusCode = 404; // 设置响应码
res.write('123');// 写入消息体
res.end();
})
server.listen(8081);// 服务器监听端口8081
server.on('listening', ()=>{
console.log("server is listening 8081");
})
实现静态资源服务器
const http = require("http");
const URL = require("url");
const path = require("path");
const fs = require("fs");
async function getStat(filename) {
try {
return await fs.promises.stat(filename);
} catch {
return null;
}
}
/**
* 得到要处理的文件内容
*/
async function getFileContent(url) {
const urlObj = URL.parse(url);
let filename; //要处理的文件路径
filename = path.resolve(__dirname, "public", urlObj.pathname.substr(1));
let stat = await getStat(filename);
if (!stat) {
//文件不存在
return null;
} else if (stat.isDirectory()) {
//文件是一个目录
filename = path.resolve(
__dirname,
"public",
urlObj.pathname.substr(1),
"index.html"
);
stat = await getStat(filename);
if (!stat) {
return null;
} else {
return await fs.promises.readFile(filename);
}
} else {
return await fs.promises.readFile(filename);
}
}
async function handler(req, res) {
const info = await getFileContent(req.url);
if (info) {
res.write(info);
} else {
res.statusCode = 404;
res.write("Resource is not exist");
}
res.end();
}
const server = http.createServer(handler);
server.on("listening", () => {
console.log("server listen 3000");
});
server.listen(3000);
通过 url、path 模块将客户端的请求地址进行处理,当地址对应的服务器资源存在时正常返回。当地址是一个目录时将地址进行拼接默认资源。再根据拼接后的地址,通过 fs 模块得到资源信息判断是否有效。最终得到处理结果时如果是一个非法资源返回404状态码和提示信息。
总结
- 客户端:
- 请求: ClientRequest 对象
- 响应:IncomingMessage 对象
- 服务器:
- 请求:IncomingMessage 对象
- 响应:ServerResponse 对象
https 模块
网络结构:
- 浏览器 + node 浏览器请求 node 服务器 node 中开启 https,node 服务器 https 默认端口是
443。 - 浏览器 + nginx + node。 浏览器请求 nginx 服务器在 nginx 上开启 https。 node 服务器则开启 http 服务, http 默认端口
80。 在 node 服务器中开启的端口只会被内部访问。
证书
网上购买证书或本地生成证书。
利用 openssl 生成CA私钥和公钥生成CA证书,生成服务器私钥和公钥生成服务器证书。
const server = https.createServer(
{
key: fs.readFileSync(path.resolve(__dirname, "./server-key.pem")), //私钥
cert: fs.readFileSync(path.resolve(__dirname, "./server-cert.crt"))
},
handler
);