NodeJs全集(五)

122 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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 模块

网络结构:

  1. 浏览器 + node 浏览器请求 node 服务器 node 中开启 https,node 服务器 https 默认端口是443
  2. 浏览器 + 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

);